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 
useFramePointerForTargetByDefault(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)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 
815f757f3fSDimitry Andric   if (Triple.isAndroid()) {
825f757f3fSDimitry Andric     switch (Triple.getArch()) {
835f757f3fSDimitry Andric     case llvm::Triple::aarch64:
845f757f3fSDimitry Andric     case llvm::Triple::arm:
855f757f3fSDimitry Andric     case llvm::Triple::armeb:
865f757f3fSDimitry Andric     case llvm::Triple::thumb:
875f757f3fSDimitry Andric     case llvm::Triple::thumbeb:
885f757f3fSDimitry Andric     case llvm::Triple::riscv64:
895f757f3fSDimitry Andric       return true;
905f757f3fSDimitry Andric     default:
915f757f3fSDimitry Andric       break;
925f757f3fSDimitry Andric     }
935f757f3fSDimitry Andric   }
945f757f3fSDimitry Andric 
955f757f3fSDimitry Andric   switch (Triple.getArch()) {
965f757f3fSDimitry Andric   case llvm::Triple::xcore:
975f757f3fSDimitry Andric   case llvm::Triple::wasm32:
985f757f3fSDimitry Andric   case llvm::Triple::wasm64:
995f757f3fSDimitry Andric   case llvm::Triple::msp430:
1005f757f3fSDimitry Andric     // XCore never wants frame pointers, regardless of OS.
1015f757f3fSDimitry Andric     // WebAssembly never wants frame pointers.
1025f757f3fSDimitry Andric     return false;
1035f757f3fSDimitry Andric   case llvm::Triple::ppc:
1045f757f3fSDimitry Andric   case llvm::Triple::ppcle:
1055f757f3fSDimitry Andric   case llvm::Triple::ppc64:
1065f757f3fSDimitry Andric   case llvm::Triple::ppc64le:
1075f757f3fSDimitry Andric   case llvm::Triple::riscv32:
1085f757f3fSDimitry Andric   case llvm::Triple::riscv64:
1095f757f3fSDimitry Andric   case llvm::Triple::sparc:
1105f757f3fSDimitry Andric   case llvm::Triple::sparcel:
1115f757f3fSDimitry Andric   case llvm::Triple::sparcv9:
1125f757f3fSDimitry Andric   case llvm::Triple::amdgcn:
1135f757f3fSDimitry Andric   case llvm::Triple::r600:
1145f757f3fSDimitry Andric   case llvm::Triple::csky:
1155f757f3fSDimitry Andric   case llvm::Triple::loongarch32:
1165f757f3fSDimitry Andric   case llvm::Triple::loongarch64:
1175f757f3fSDimitry Andric     return !clang::driver::tools::areOptimizationsEnabled(Args);
1185f757f3fSDimitry Andric   default:
1195f757f3fSDimitry Andric     break;
1205f757f3fSDimitry Andric   }
1215f757f3fSDimitry Andric 
1225f757f3fSDimitry Andric   if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) {
1235f757f3fSDimitry Andric     return !clang::driver::tools::areOptimizationsEnabled(Args);
1245f757f3fSDimitry Andric   }
1255f757f3fSDimitry Andric 
1265f757f3fSDimitry Andric   if (Triple.isOSLinux() || Triple.isOSHurd()) {
1275f757f3fSDimitry Andric     switch (Triple.getArch()) {
1285f757f3fSDimitry Andric     // Don't use a frame pointer on linux if optimizing for certain targets.
1295f757f3fSDimitry Andric     case llvm::Triple::arm:
1305f757f3fSDimitry Andric     case llvm::Triple::armeb:
1315f757f3fSDimitry Andric     case llvm::Triple::thumb:
1325f757f3fSDimitry Andric     case llvm::Triple::thumbeb:
1335f757f3fSDimitry Andric     case llvm::Triple::mips64:
1345f757f3fSDimitry Andric     case llvm::Triple::mips64el:
1355f757f3fSDimitry Andric     case llvm::Triple::mips:
1365f757f3fSDimitry Andric     case llvm::Triple::mipsel:
1375f757f3fSDimitry Andric     case llvm::Triple::systemz:
1385f757f3fSDimitry Andric     case llvm::Triple::x86:
1395f757f3fSDimitry Andric     case llvm::Triple::x86_64:
1405f757f3fSDimitry Andric       return !clang::driver::tools::areOptimizationsEnabled(Args);
1415f757f3fSDimitry Andric     default:
1425f757f3fSDimitry Andric       return true;
1435f757f3fSDimitry Andric     }
1445f757f3fSDimitry Andric   }
1455f757f3fSDimitry Andric 
1465f757f3fSDimitry Andric   if (Triple.isOSWindows()) {
1475f757f3fSDimitry Andric     switch (Triple.getArch()) {
1485f757f3fSDimitry Andric     case llvm::Triple::x86:
1495f757f3fSDimitry Andric       return !clang::driver::tools::areOptimizationsEnabled(Args);
1505f757f3fSDimitry Andric     case llvm::Triple::x86_64:
1515f757f3fSDimitry Andric       return Triple.isOSBinFormatMachO();
1525f757f3fSDimitry Andric     case llvm::Triple::arm:
1535f757f3fSDimitry Andric     case llvm::Triple::thumb:
1545f757f3fSDimitry Andric       // Windows on ARM builds with FPO disabled to aid fast stack walking
1555f757f3fSDimitry Andric       return true;
1565f757f3fSDimitry Andric     default:
1575f757f3fSDimitry Andric       // All other supported Windows ISAs use xdata unwind information, so frame
1585f757f3fSDimitry Andric       // pointers are not generally useful.
1595f757f3fSDimitry Andric       return false;
1605f757f3fSDimitry Andric     }
1615f757f3fSDimitry Andric   }
1625f757f3fSDimitry Andric 
1635f757f3fSDimitry Andric   return true;
1645f757f3fSDimitry Andric }
1655f757f3fSDimitry Andric 
mustUseNonLeafFramePointerForTarget(const llvm::Triple & Triple)1665f757f3fSDimitry Andric static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
1675f757f3fSDimitry Andric   switch (Triple.getArch()) {
1685f757f3fSDimitry Andric   default:
1695f757f3fSDimitry Andric     return false;
1705f757f3fSDimitry Andric   case llvm::Triple::arm:
1715f757f3fSDimitry Andric   case llvm::Triple::thumb:
1725f757f3fSDimitry Andric     // ARM Darwin targets require a frame pointer to be always present to aid
1735f757f3fSDimitry Andric     // offline debugging via backtraces.
1745f757f3fSDimitry Andric     return Triple.isOSDarwin();
1755f757f3fSDimitry Andric   }
1765f757f3fSDimitry Andric }
1775f757f3fSDimitry Andric 
1785f757f3fSDimitry Andric clang::CodeGenOptions::FramePointerKind
getFramePointerKind(const llvm::opt::ArgList & Args,const llvm::Triple & Triple)1795f757f3fSDimitry Andric getFramePointerKind(const llvm::opt::ArgList &Args,
1805f757f3fSDimitry Andric                     const llvm::Triple &Triple) {
1815f757f3fSDimitry Andric   // We have 4 states:
1825f757f3fSDimitry Andric   //
1835f757f3fSDimitry Andric   //  00) leaf retained, non-leaf retained
1845f757f3fSDimitry Andric   //  01) leaf retained, non-leaf omitted (this is invalid)
1855f757f3fSDimitry Andric   //  10) leaf omitted, non-leaf retained
1865f757f3fSDimitry Andric   //      (what -momit-leaf-frame-pointer was designed for)
1875f757f3fSDimitry Andric   //  11) leaf omitted, non-leaf omitted
1885f757f3fSDimitry Andric   //
1895f757f3fSDimitry Andric   //  "omit" options taking precedence over "no-omit" options is the only way
1905f757f3fSDimitry Andric   //  to make 3 valid states representable
1915f757f3fSDimitry Andric   llvm::opt::Arg *A =
1925f757f3fSDimitry Andric       Args.getLastArg(clang::driver::options::OPT_fomit_frame_pointer,
1935f757f3fSDimitry Andric                       clang::driver::options::OPT_fno_omit_frame_pointer);
1945f757f3fSDimitry Andric 
1955f757f3fSDimitry Andric   bool OmitFP = A && A->getOption().matches(
1965f757f3fSDimitry Andric                          clang::driver::options::OPT_fomit_frame_pointer);
1975f757f3fSDimitry Andric   bool NoOmitFP = A && A->getOption().matches(
1985f757f3fSDimitry Andric                            clang::driver::options::OPT_fno_omit_frame_pointer);
1995f757f3fSDimitry Andric   bool OmitLeafFP =
2005f757f3fSDimitry Andric       Args.hasFlag(clang::driver::options::OPT_momit_leaf_frame_pointer,
2015f757f3fSDimitry Andric                    clang::driver::options::OPT_mno_omit_leaf_frame_pointer,
2025f757f3fSDimitry Andric                    Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
2035f757f3fSDimitry Andric                        (Triple.isAndroid() && Triple.isRISCV64()));
2045f757f3fSDimitry Andric   if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
2055f757f3fSDimitry Andric       (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
2065f757f3fSDimitry Andric     if (OmitLeafFP)
2075f757f3fSDimitry Andric       return clang::CodeGenOptions::FramePointerKind::NonLeaf;
2085f757f3fSDimitry Andric     return clang::CodeGenOptions::FramePointerKind::All;
2095f757f3fSDimitry Andric   }
2105f757f3fSDimitry Andric   return clang::CodeGenOptions::FramePointerKind::None;
2115f757f3fSDimitry Andric }
2125f757f3fSDimitry Andric 
renderRpassOptions(const ArgList & Args,ArgStringList & CmdArgs,const StringRef PluginOptPrefix)213bdd1243dSDimitry Andric static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs,
214bdd1243dSDimitry Andric                                const StringRef PluginOptPrefix) {
215e8d8bef9SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
216bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
217bdd1243dSDimitry Andric                                          "-pass-remarks=" + A->getValue()));
218e8d8bef9SDimitry Andric 
219e8d8bef9SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
220e8d8bef9SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
221bdd1243dSDimitry Andric         Twine(PluginOptPrefix) + "-pass-remarks-missed=" + A->getValue()));
222e8d8bef9SDimitry Andric 
223e8d8bef9SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
224e8d8bef9SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
225bdd1243dSDimitry Andric         Twine(PluginOptPrefix) + "-pass-remarks-analysis=" + A->getValue()));
226e8d8bef9SDimitry Andric }
227e8d8bef9SDimitry Andric 
renderRemarksOptions(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple,const InputInfo & Input,const InputInfo & Output,const StringRef PluginOptPrefix)228e8d8bef9SDimitry Andric static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
229e8d8bef9SDimitry Andric                                  const llvm::Triple &Triple,
230e8d8bef9SDimitry Andric                                  const InputInfo &Input,
231bdd1243dSDimitry Andric                                  const InputInfo &Output,
232bdd1243dSDimitry Andric                                  const StringRef PluginOptPrefix) {
233e8d8bef9SDimitry Andric   StringRef Format = "yaml";
234e8d8bef9SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
235e8d8bef9SDimitry Andric     Format = A->getValue();
236e8d8bef9SDimitry Andric 
237e8d8bef9SDimitry Andric   SmallString<128> F;
238e8d8bef9SDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
239e8d8bef9SDimitry Andric   if (A)
240e8d8bef9SDimitry Andric     F = A->getValue();
241e8d8bef9SDimitry Andric   else if (Output.isFilename())
242e8d8bef9SDimitry Andric     F = Output.getFilename();
243e8d8bef9SDimitry Andric 
244e8d8bef9SDimitry Andric   assert(!F.empty() && "Cannot determine remarks output name.");
245e8d8bef9SDimitry Andric   // Append "opt.ld.<format>" to the end of the file name.
246bdd1243dSDimitry Andric   CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
247bdd1243dSDimitry Andric                                        "opt-remarks-filename=" + F +
248bdd1243dSDimitry Andric                                        ".opt.ld." + Format));
249e8d8bef9SDimitry Andric 
250e8d8bef9SDimitry Andric   if (const Arg *A =
251e8d8bef9SDimitry Andric           Args.getLastArg(options::OPT_foptimization_record_passes_EQ))
252e8d8bef9SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
253bdd1243dSDimitry Andric         Twine(PluginOptPrefix) + "opt-remarks-passes=" + A->getValue()));
254e8d8bef9SDimitry Andric 
255bdd1243dSDimitry Andric   CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
256bdd1243dSDimitry Andric                                        "opt-remarks-format=" + Format.data()));
257e8d8bef9SDimitry Andric }
258e8d8bef9SDimitry Andric 
renderRemarksHotnessOptions(const ArgList & Args,ArgStringList & CmdArgs,const StringRef PluginOptPrefix)259e8d8bef9SDimitry Andric static void renderRemarksHotnessOptions(const ArgList &Args,
260bdd1243dSDimitry Andric                                         ArgStringList &CmdArgs,
261bdd1243dSDimitry Andric                                         const StringRef PluginOptPrefix) {
262e8d8bef9SDimitry Andric   if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
263e8d8bef9SDimitry Andric                    options::OPT_fno_diagnostics_show_hotness, false))
264bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
265bdd1243dSDimitry Andric                                          "opt-remarks-with-hotness"));
266e8d8bef9SDimitry Andric 
267e8d8bef9SDimitry Andric   if (const Arg *A =
268e8d8bef9SDimitry Andric           Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ))
269bdd1243dSDimitry Andric     CmdArgs.push_back(
270bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) +
271bdd1243dSDimitry Andric                            "opt-remarks-hotness-threshold=" + A->getValue()));
272e8d8bef9SDimitry Andric }
273e8d8bef9SDimitry Andric 
shouldIgnoreUnsupportedTargetFeature(const Arg & TargetFeatureArg,llvm::Triple T,StringRef Processor)27406c3fb27SDimitry Andric static bool shouldIgnoreUnsupportedTargetFeature(const Arg &TargetFeatureArg,
27506c3fb27SDimitry Andric                                                  llvm::Triple T,
27606c3fb27SDimitry Andric                                                  StringRef Processor) {
27706c3fb27SDimitry Andric   // Warn no-cumode for AMDGCN processors not supporing WGP mode.
27806c3fb27SDimitry Andric   if (!T.isAMDGPU())
27906c3fb27SDimitry Andric     return false;
28006c3fb27SDimitry Andric   auto GPUKind = T.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
28106c3fb27SDimitry Andric                               : llvm::AMDGPU::parseArchR600(Processor);
28206c3fb27SDimitry Andric   auto GPUFeatures = T.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(GPUKind)
28306c3fb27SDimitry Andric                                   : llvm::AMDGPU::getArchAttrR600(GPUKind);
28406c3fb27SDimitry Andric   if (GPUFeatures & llvm::AMDGPU::FEATURE_WGP)
28506c3fb27SDimitry Andric     return false;
28606c3fb27SDimitry Andric   return TargetFeatureArg.getOption().matches(options::OPT_mno_cumode);
28706c3fb27SDimitry Andric }
28806c3fb27SDimitry Andric 
addPathIfExists(const Driver & D,const Twine & Path,ToolChain::path_list & Paths)2890b57cec5SDimitry Andric void tools::addPathIfExists(const Driver &D, const Twine &Path,
2900b57cec5SDimitry Andric                             ToolChain::path_list &Paths) {
2910b57cec5SDimitry Andric   if (D.getVFS().exists(Path))
2920b57cec5SDimitry Andric     Paths.push_back(Path.str());
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
handleTargetFeaturesGroup(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features,OptSpecifier Group)29506c3fb27SDimitry Andric void tools::handleTargetFeaturesGroup(const Driver &D,
29606c3fb27SDimitry Andric                                       const llvm::Triple &Triple,
29706c3fb27SDimitry Andric                                       const ArgList &Args,
2980b57cec5SDimitry Andric                                       std::vector<StringRef> &Features,
2990b57cec5SDimitry Andric                                       OptSpecifier Group) {
30006c3fb27SDimitry Andric   std::set<StringRef> Warned;
3010b57cec5SDimitry Andric   for (const Arg *A : Args.filtered(Group)) {
3020b57cec5SDimitry Andric     StringRef Name = A->getOption().getName();
3030b57cec5SDimitry Andric     A->claim();
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric     // Skip over "-m".
3065f757f3fSDimitry Andric     assert(Name.starts_with("m") && "Invalid feature name.");
3070b57cec5SDimitry Andric     Name = Name.substr(1);
3080b57cec5SDimitry Andric 
30906c3fb27SDimitry Andric     auto Proc = getCPUName(D, Args, Triple);
31006c3fb27SDimitry Andric     if (shouldIgnoreUnsupportedTargetFeature(*A, Triple, Proc)) {
31106c3fb27SDimitry Andric       if (Warned.count(Name) == 0) {
31206c3fb27SDimitry Andric         D.getDiags().Report(
31306c3fb27SDimitry Andric             clang::diag::warn_drv_unsupported_option_for_processor)
31406c3fb27SDimitry Andric             << A->getAsString(Args) << Proc;
31506c3fb27SDimitry Andric         Warned.insert(Name);
31606c3fb27SDimitry Andric       }
31706c3fb27SDimitry Andric       continue;
31806c3fb27SDimitry Andric     }
31906c3fb27SDimitry Andric 
3205f757f3fSDimitry Andric     bool IsNegative = Name.starts_with("no-");
3210b57cec5SDimitry Andric     if (IsNegative)
3220b57cec5SDimitry Andric       Name = Name.substr(3);
32306c3fb27SDimitry Andric 
3240b57cec5SDimitry Andric     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
32881ad6265SDimitry Andric SmallVector<StringRef>
unifyTargetFeatures(ArrayRef<StringRef> Features)32981ad6265SDimitry Andric tools::unifyTargetFeatures(ArrayRef<StringRef> Features) {
33081ad6265SDimitry Andric   // Only add a feature if it hasn't been seen before starting from the end.
33181ad6265SDimitry Andric   SmallVector<StringRef> UnifiedFeatures;
33281ad6265SDimitry Andric   llvm::DenseSet<StringRef> UsedFeatures;
33381ad6265SDimitry Andric   for (StringRef Feature : llvm::reverse(Features)) {
33481ad6265SDimitry Andric     if (UsedFeatures.insert(Feature.drop_front()).second)
33581ad6265SDimitry Andric       UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature);
3365ffd83dbSDimitry Andric   }
3375ffd83dbSDimitry Andric 
3385ffd83dbSDimitry Andric   return UnifiedFeatures;
3395ffd83dbSDimitry Andric }
3405ffd83dbSDimitry Andric 
addDirectoryList(const ArgList & Args,ArgStringList & CmdArgs,const char * ArgName,const char * EnvVar)3410b57cec5SDimitry Andric void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
3420b57cec5SDimitry Andric                              const char *ArgName, const char *EnvVar) {
3430b57cec5SDimitry Andric   const char *DirList = ::getenv(EnvVar);
3440b57cec5SDimitry Andric   bool CombinedArg = false;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   if (!DirList)
3470b57cec5SDimitry Andric     return; // Nothing to do.
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   StringRef Name(ArgName);
3505ffd83dbSDimitry Andric   if (Name.equals("-I") || Name.equals("-L") || Name.empty())
3510b57cec5SDimitry Andric     CombinedArg = true;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   StringRef Dirs(DirList);
3540b57cec5SDimitry Andric   if (Dirs.empty()) // Empty string should not add '.'.
3550b57cec5SDimitry Andric     return;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   StringRef::size_type Delim;
3580b57cec5SDimitry Andric   while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
3590b57cec5SDimitry Andric     if (Delim == 0) { // Leading colon.
3600b57cec5SDimitry Andric       if (CombinedArg) {
3610b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
3620b57cec5SDimitry Andric       } else {
3630b57cec5SDimitry Andric         CmdArgs.push_back(ArgName);
3640b57cec5SDimitry Andric         CmdArgs.push_back(".");
3650b57cec5SDimitry Andric       }
3660b57cec5SDimitry Andric     } else {
3670b57cec5SDimitry Andric       if (CombinedArg) {
3680b57cec5SDimitry Andric         CmdArgs.push_back(
3690b57cec5SDimitry Andric             Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
3700b57cec5SDimitry Andric       } else {
3710b57cec5SDimitry Andric         CmdArgs.push_back(ArgName);
3720b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
3730b57cec5SDimitry Andric       }
3740b57cec5SDimitry Andric     }
3750b57cec5SDimitry Andric     Dirs = Dirs.substr(Delim + 1);
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   if (Dirs.empty()) { // Trailing colon.
3790b57cec5SDimitry Andric     if (CombinedArg) {
3800b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
3810b57cec5SDimitry Andric     } else {
3820b57cec5SDimitry Andric       CmdArgs.push_back(ArgName);
3830b57cec5SDimitry Andric       CmdArgs.push_back(".");
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric   } else { // Add the last path.
3860b57cec5SDimitry Andric     if (CombinedArg) {
3870b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
3880b57cec5SDimitry Andric     } else {
3890b57cec5SDimitry Andric       CmdArgs.push_back(ArgName);
3900b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Dirs));
3910b57cec5SDimitry Andric     }
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
AddLinkerInputs(const ToolChain & TC,const InputInfoList & Inputs,const ArgList & Args,ArgStringList & CmdArgs,const JobAction & JA)3950b57cec5SDimitry Andric void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
3960b57cec5SDimitry Andric                             const ArgList &Args, ArgStringList &CmdArgs,
3970b57cec5SDimitry Andric                             const JobAction &JA) {
3980b57cec5SDimitry Andric   const Driver &D = TC.getDriver();
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   // Add extra linker input arguments which are not treated as inputs
4010b57cec5SDimitry Andric   // (constructed via -Xarch_).
4020b57cec5SDimitry Andric   Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
4030b57cec5SDimitry Andric 
404a7dea167SDimitry Andric   // LIBRARY_PATH are included before user inputs and only supported on native
405a7dea167SDimitry Andric   // toolchains.
406a7dea167SDimitry Andric   if (!TC.isCrossCompiling())
407a7dea167SDimitry Andric     addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
408a7dea167SDimitry Andric 
4090b57cec5SDimitry Andric   for (const auto &II : Inputs) {
4105ffd83dbSDimitry Andric     // If the current tool chain refers to an OpenMP offloading host, we
4115ffd83dbSDimitry Andric     // should ignore inputs that refer to OpenMP offloading devices -
4120b57cec5SDimitry Andric     // they will be embedded according to a proper linker script.
4130b57cec5SDimitry Andric     if (auto *IA = II.getAction())
4140b57cec5SDimitry Andric       if ((JA.isHostOffloading(Action::OFK_OpenMP) &&
4155ffd83dbSDimitry Andric            IA->isDeviceOffloading(Action::OFK_OpenMP)))
4160b57cec5SDimitry Andric         continue;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
4190b57cec5SDimitry Andric       // Don't try to pass LLVM inputs unless we have native support.
4200b57cec5SDimitry Andric       D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     // Add filenames immediately.
4230b57cec5SDimitry Andric     if (II.isFilename()) {
4240b57cec5SDimitry Andric       CmdArgs.push_back(II.getFilename());
4250b57cec5SDimitry Andric       continue;
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric 
42881ad6265SDimitry Andric     // In some error cases, the input could be Nothing; skip those.
42981ad6265SDimitry Andric     if (II.isNothing())
43081ad6265SDimitry Andric       continue;
43181ad6265SDimitry Andric 
4320b57cec5SDimitry Andric     // Otherwise, this is a linker input argument.
4330b57cec5SDimitry Andric     const Arg &A = II.getInputArg();
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric     // Handle reserved library options.
4360b57cec5SDimitry Andric     if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
4370b57cec5SDimitry Andric       TC.AddCXXStdlibLibArgs(Args, CmdArgs);
4380b57cec5SDimitry Andric     else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
4390b57cec5SDimitry Andric       TC.AddCCKextLibArgs(Args, CmdArgs);
44006c3fb27SDimitry Andric     else
4410b57cec5SDimitry Andric       A.renderAsInput(Args, CmdArgs);
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric 
addLinkerCompressDebugSectionsOption(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)44519587d74SEd Maste void tools::addLinkerCompressDebugSectionsOption(
44619587d74SEd Maste     const ToolChain &TC, const llvm::opt::ArgList &Args,
44719587d74SEd Maste     llvm::opt::ArgStringList &CmdArgs) {
44819587d74SEd Maste   // GNU ld supports --compress-debug-sections=none|zlib|zlib-gnu|zlib-gabi
44904eeddc0SDimitry Andric   // whereas zlib is an alias to zlib-gabi and zlib-gnu is obsoleted. Therefore
45004eeddc0SDimitry Andric   // -gz=none|zlib are translated to --compress-debug-sections=none|zlib. -gz
45104eeddc0SDimitry Andric   // is not translated since ld --compress-debug-sections option requires an
45219587d74SEd Maste   // argument.
45319587d74SEd Maste   if (const Arg *A = Args.getLastArg(options::OPT_gz_EQ)) {
45419587d74SEd Maste     StringRef V = A->getValue();
455bdd1243dSDimitry Andric     if (V == "none" || V == "zlib" || V == "zstd")
45619587d74SEd Maste       CmdArgs.push_back(Args.MakeArgString("--compress-debug-sections=" + V));
45719587d74SEd Maste     else
45819587d74SEd Maste       TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
459bdd1243dSDimitry Andric           << A->getSpelling() << V;
46019587d74SEd Maste   }
46119587d74SEd Maste }
46219587d74SEd Maste 
AddTargetFeature(const ArgList & Args,std::vector<StringRef> & Features,OptSpecifier OnOpt,OptSpecifier OffOpt,StringRef FeatureName)4630b57cec5SDimitry Andric void tools::AddTargetFeature(const ArgList &Args,
4640b57cec5SDimitry Andric                              std::vector<StringRef> &Features,
4650b57cec5SDimitry Andric                              OptSpecifier OnOpt, OptSpecifier OffOpt,
4660b57cec5SDimitry Andric                              StringRef FeatureName) {
4670b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
4680b57cec5SDimitry Andric     if (A->getOption().matches(OnOpt))
4690b57cec5SDimitry Andric       Features.push_back(Args.MakeArgString("+" + FeatureName));
4700b57cec5SDimitry Andric     else
4710b57cec5SDimitry Andric       Features.push_back(Args.MakeArgString("-" + FeatureName));
4720b57cec5SDimitry Andric   }
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
475e8d8bef9SDimitry Andric /// Get the (LLVM) name of the AMDGPU gpu we are targeting.
getAMDGPUTargetGPU(const llvm::Triple & T,const ArgList & Args)476e8d8bef9SDimitry Andric static std::string getAMDGPUTargetGPU(const llvm::Triple &T,
477e8d8bef9SDimitry Andric                                       const ArgList &Args) {
47806c3fb27SDimitry Andric   Arg *MArch = Args.getLastArg(options::OPT_march_EQ);
4790b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
480e8d8bef9SDimitry Andric     auto GPUName = getProcessorFromTargetID(T, A->getValue());
481e8d8bef9SDimitry Andric     return llvm::StringSwitch<std::string>(GPUName)
4820b57cec5SDimitry Andric         .Cases("rv630", "rv635", "r600")
4830b57cec5SDimitry Andric         .Cases("rv610", "rv620", "rs780", "rs880")
4840b57cec5SDimitry Andric         .Case("rv740", "rv770")
4850b57cec5SDimitry Andric         .Case("palm", "cedar")
4860b57cec5SDimitry Andric         .Cases("sumo", "sumo2", "sumo")
4870b57cec5SDimitry Andric         .Case("hemlock", "cypress")
4880b57cec5SDimitry Andric         .Case("aruba", "cayman")
489e8d8bef9SDimitry Andric         .Default(GPUName.str());
4900b57cec5SDimitry Andric   }
49106c3fb27SDimitry Andric   if (MArch)
49206c3fb27SDimitry Andric     return getProcessorFromTargetID(T, MArch->getValue()).str();
4930b57cec5SDimitry Andric   return "";
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
getLanaiTargetCPU(const ArgList & Args)4960b57cec5SDimitry Andric static std::string getLanaiTargetCPU(const ArgList &Args) {
4970b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
4980b57cec5SDimitry Andric     return A->getValue();
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric   return "";
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric /// Get the (LLVM) name of the WebAssembly cpu we are targeting.
getWebAssemblyTargetCPU(const ArgList & Args)5040b57cec5SDimitry Andric static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
5050b57cec5SDimitry Andric   // If we have -mcpu=, use that.
5060b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
5070b57cec5SDimitry Andric     StringRef CPU = A->getValue();
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric #ifdef __wasm__
5100b57cec5SDimitry Andric     // Handle "native" by examining the host. "native" isn't meaningful when
5110b57cec5SDimitry Andric     // cross compiling, so only support this when the host is also WebAssembly.
5120b57cec5SDimitry Andric     if (CPU == "native")
5130b57cec5SDimitry Andric       return llvm::sys::getHostCPUName();
5140b57cec5SDimitry Andric #endif
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric     return CPU;
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   return "generic";
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric 
getCPUName(const Driver & D,const ArgList & Args,const llvm::Triple & T,bool FromAs)522349cc55cSDimitry Andric std::string tools::getCPUName(const Driver &D, const ArgList &Args,
523349cc55cSDimitry Andric                               const llvm::Triple &T, bool FromAs) {
5240b57cec5SDimitry Andric   Arg *A;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   switch (T.getArch()) {
5270b57cec5SDimitry Andric   default:
5280b57cec5SDimitry Andric     return "";
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   case llvm::Triple::aarch64:
531480093f4SDimitry Andric   case llvm::Triple::aarch64_32:
5320b57cec5SDimitry Andric   case llvm::Triple::aarch64_be:
5330b57cec5SDimitry Andric     return aarch64::getAArch64TargetCPU(Args, T, A);
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   case llvm::Triple::arm:
5360b57cec5SDimitry Andric   case llvm::Triple::armeb:
5370b57cec5SDimitry Andric   case llvm::Triple::thumb:
5380b57cec5SDimitry Andric   case llvm::Triple::thumbeb: {
5390b57cec5SDimitry Andric     StringRef MArch, MCPU;
5400b57cec5SDimitry Andric     arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
5410b57cec5SDimitry Andric     return arm::getARMTargetCPU(MCPU, MArch, T);
5420b57cec5SDimitry Andric   }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   case llvm::Triple::avr:
5450b57cec5SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ))
5460b57cec5SDimitry Andric       return A->getValue();
5470b57cec5SDimitry Andric     return "";
5480b57cec5SDimitry Andric 
549fe6060f1SDimitry Andric   case llvm::Triple::m68k:
550fe6060f1SDimitry Andric     return m68k::getM68kTargetCPU(Args);
551fe6060f1SDimitry Andric 
5520b57cec5SDimitry Andric   case llvm::Triple::mips:
5530b57cec5SDimitry Andric   case llvm::Triple::mipsel:
5540b57cec5SDimitry Andric   case llvm::Triple::mips64:
5550b57cec5SDimitry Andric   case llvm::Triple::mips64el: {
5560b57cec5SDimitry Andric     StringRef CPUName;
5570b57cec5SDimitry Andric     StringRef ABIName;
5580b57cec5SDimitry Andric     mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
5595ffd83dbSDimitry Andric     return std::string(CPUName);
5600b57cec5SDimitry Andric   }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   case llvm::Triple::nvptx:
5630b57cec5SDimitry Andric   case llvm::Triple::nvptx64:
5640b57cec5SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
5650b57cec5SDimitry Andric       return A->getValue();
5660b57cec5SDimitry Andric     return "";
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   case llvm::Triple::ppc:
569e8d8bef9SDimitry Andric   case llvm::Triple::ppcle:
5700b57cec5SDimitry Andric   case llvm::Triple::ppc64:
571bdd1243dSDimitry Andric   case llvm::Triple::ppc64le:
57206c3fb27SDimitry Andric     return ppc::getPPCTargetCPU(D, Args, T);
5735ffd83dbSDimitry Andric 
57481ad6265SDimitry Andric   case llvm::Triple::csky:
57581ad6265SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
57681ad6265SDimitry Andric       return A->getValue();
57781ad6265SDimitry Andric     else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
57881ad6265SDimitry Andric       return A->getValue();
57981ad6265SDimitry Andric     else
58081ad6265SDimitry Andric       return "ck810";
581590d96feSDimitry Andric   case llvm::Triple::riscv32:
582590d96feSDimitry Andric   case llvm::Triple::riscv64:
583bdd1243dSDimitry Andric     return riscv::getRISCVTargetCPU(Args, T);
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   case llvm::Triple::bpfel:
5860b57cec5SDimitry Andric   case llvm::Triple::bpfeb:
58761cfbce3SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
58861cfbce3SDimitry Andric       return A->getValue();
58961cfbce3SDimitry Andric     return "";
59061cfbce3SDimitry Andric 
5910b57cec5SDimitry Andric   case llvm::Triple::sparc:
5920b57cec5SDimitry Andric   case llvm::Triple::sparcel:
5930b57cec5SDimitry Andric   case llvm::Triple::sparcv9:
59461cfbce3SDimitry Andric     return sparc::getSparcTargetCPU(D, Args, T);
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   case llvm::Triple::x86:
5970b57cec5SDimitry Andric   case llvm::Triple::x86_64:
598349cc55cSDimitry Andric     return x86::getX86TargetCPU(D, Args, T);
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   case llvm::Triple::hexagon:
6010b57cec5SDimitry Andric     return "hexagon" +
6020b57cec5SDimitry Andric            toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   case llvm::Triple::lanai:
6050b57cec5SDimitry Andric     return getLanaiTargetCPU(Args);
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   case llvm::Triple::systemz:
6080b57cec5SDimitry Andric     return systemz::getSystemZTargetCPU(Args);
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   case llvm::Triple::r600:
6110b57cec5SDimitry Andric   case llvm::Triple::amdgcn:
612e8d8bef9SDimitry Andric     return getAMDGPUTargetGPU(T, Args);
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   case llvm::Triple::wasm32:
6150b57cec5SDimitry Andric   case llvm::Triple::wasm64:
6165ffd83dbSDimitry Andric     return std::string(getWebAssemblyTargetCPU(Args));
6178a4dda33SDimitry Andric 
6188a4dda33SDimitry Andric   case llvm::Triple::loongarch32:
6198a4dda33SDimitry Andric   case llvm::Triple::loongarch64:
6208a4dda33SDimitry Andric     return loongarch::getLoongArchTargetCPU(Args, T);
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
getWebAssemblyTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)62406c3fb27SDimitry Andric static void getWebAssemblyTargetFeatures(const Driver &D,
62506c3fb27SDimitry Andric                                          const llvm::Triple &Triple,
62606c3fb27SDimitry Andric                                          const ArgList &Args,
627bdd1243dSDimitry Andric                                          std::vector<StringRef> &Features) {
62806c3fb27SDimitry Andric   handleTargetFeaturesGroup(D, Triple, Args, Features,
62906c3fb27SDimitry Andric                             options::OPT_m_wasm_Features_Group);
630bdd1243dSDimitry Andric }
631bdd1243dSDimitry Andric 
getTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,bool ForAS,bool IsAux)632bdd1243dSDimitry Andric void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
633bdd1243dSDimitry Andric                               const ArgList &Args, ArgStringList &CmdArgs,
634bdd1243dSDimitry Andric                               bool ForAS, bool IsAux) {
635bdd1243dSDimitry Andric   std::vector<StringRef> Features;
636bdd1243dSDimitry Andric   switch (Triple.getArch()) {
637bdd1243dSDimitry Andric   default:
638bdd1243dSDimitry Andric     break;
639bdd1243dSDimitry Andric   case llvm::Triple::mips:
640bdd1243dSDimitry Andric   case llvm::Triple::mipsel:
641bdd1243dSDimitry Andric   case llvm::Triple::mips64:
642bdd1243dSDimitry Andric   case llvm::Triple::mips64el:
643bdd1243dSDimitry Andric     mips::getMIPSTargetFeatures(D, Triple, Args, Features);
644bdd1243dSDimitry Andric     break;
645bdd1243dSDimitry Andric   case llvm::Triple::arm:
646bdd1243dSDimitry Andric   case llvm::Triple::armeb:
647bdd1243dSDimitry Andric   case llvm::Triple::thumb:
648bdd1243dSDimitry Andric   case llvm::Triple::thumbeb:
649bdd1243dSDimitry Andric     arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS);
650bdd1243dSDimitry Andric     break;
651bdd1243dSDimitry Andric   case llvm::Triple::ppc:
652bdd1243dSDimitry Andric   case llvm::Triple::ppcle:
653bdd1243dSDimitry Andric   case llvm::Triple::ppc64:
654bdd1243dSDimitry Andric   case llvm::Triple::ppc64le:
655bdd1243dSDimitry Andric     ppc::getPPCTargetFeatures(D, Triple, Args, Features);
656bdd1243dSDimitry Andric     break;
657bdd1243dSDimitry Andric   case llvm::Triple::riscv32:
658bdd1243dSDimitry Andric   case llvm::Triple::riscv64:
659bdd1243dSDimitry Andric     riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
660bdd1243dSDimitry Andric     break;
661bdd1243dSDimitry Andric   case llvm::Triple::systemz:
662bdd1243dSDimitry Andric     systemz::getSystemZTargetFeatures(D, Args, Features);
663bdd1243dSDimitry Andric     break;
664bdd1243dSDimitry Andric   case llvm::Triple::aarch64:
665bdd1243dSDimitry Andric   case llvm::Triple::aarch64_32:
666bdd1243dSDimitry Andric   case llvm::Triple::aarch64_be:
667bdd1243dSDimitry Andric     aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
668bdd1243dSDimitry Andric     break;
669bdd1243dSDimitry Andric   case llvm::Triple::x86:
670bdd1243dSDimitry Andric   case llvm::Triple::x86_64:
671bdd1243dSDimitry Andric     x86::getX86TargetFeatures(D, Triple, Args, Features);
672bdd1243dSDimitry Andric     break;
673bdd1243dSDimitry Andric   case llvm::Triple::hexagon:
67406c3fb27SDimitry Andric     hexagon::getHexagonTargetFeatures(D, Triple, Args, Features);
675bdd1243dSDimitry Andric     break;
676bdd1243dSDimitry Andric   case llvm::Triple::wasm32:
677bdd1243dSDimitry Andric   case llvm::Triple::wasm64:
67806c3fb27SDimitry Andric     getWebAssemblyTargetFeatures(D, Triple, Args, Features);
679bdd1243dSDimitry Andric     break;
680bdd1243dSDimitry Andric   case llvm::Triple::sparc:
681bdd1243dSDimitry Andric   case llvm::Triple::sparcel:
682bdd1243dSDimitry Andric   case llvm::Triple::sparcv9:
683bdd1243dSDimitry Andric     sparc::getSparcTargetFeatures(D, Args, Features);
684bdd1243dSDimitry Andric     break;
685bdd1243dSDimitry Andric   case llvm::Triple::r600:
686bdd1243dSDimitry Andric   case llvm::Triple::amdgcn:
687bdd1243dSDimitry Andric     amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
688bdd1243dSDimitry Andric     break;
689bdd1243dSDimitry Andric   case llvm::Triple::nvptx:
690bdd1243dSDimitry Andric   case llvm::Triple::nvptx64:
691bdd1243dSDimitry Andric     NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features);
692bdd1243dSDimitry Andric     break;
693bdd1243dSDimitry Andric   case llvm::Triple::m68k:
694bdd1243dSDimitry Andric     m68k::getM68kTargetFeatures(D, Triple, Args, Features);
695bdd1243dSDimitry Andric     break;
696bdd1243dSDimitry Andric   case llvm::Triple::msp430:
697bdd1243dSDimitry Andric     msp430::getMSP430TargetFeatures(D, Args, Features);
698bdd1243dSDimitry Andric     break;
699bdd1243dSDimitry Andric   case llvm::Triple::ve:
700bdd1243dSDimitry Andric     ve::getVETargetFeatures(D, Args, Features);
701bdd1243dSDimitry Andric     break;
702bdd1243dSDimitry Andric   case llvm::Triple::csky:
703bdd1243dSDimitry Andric     csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features);
704bdd1243dSDimitry Andric     break;
705bdd1243dSDimitry Andric   case llvm::Triple::loongarch32:
706bdd1243dSDimitry Andric   case llvm::Triple::loongarch64:
707bdd1243dSDimitry Andric     loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features);
708bdd1243dSDimitry Andric     break;
709bdd1243dSDimitry Andric   }
710bdd1243dSDimitry Andric 
711bdd1243dSDimitry Andric   for (auto Feature : unifyTargetFeatures(Features)) {
712bdd1243dSDimitry Andric     CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
713bdd1243dSDimitry Andric     CmdArgs.push_back(Feature.data());
714bdd1243dSDimitry Andric   }
715bdd1243dSDimitry Andric }
716bdd1243dSDimitry Andric 
getLTOParallelism(const ArgList & Args,const Driver & D)7175ffd83dbSDimitry Andric llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
7180b57cec5SDimitry Andric   Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
7195ffd83dbSDimitry Andric   if (!LtoJobsArg)
7205ffd83dbSDimitry Andric     return {};
7215ffd83dbSDimitry Andric   if (!llvm::get_threadpool_strategy(LtoJobsArg->getValue()))
7225ffd83dbSDimitry Andric     D.Diag(diag::err_drv_invalid_int_value)
7235ffd83dbSDimitry Andric         << LtoJobsArg->getAsString(Args) << LtoJobsArg->getValue();
7245ffd83dbSDimitry Andric   return LtoJobsArg->getValue();
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7275f757f3fSDimitry Andric // PS4/PS5 uses -ffunction-sections and -fdata-sections by default.
isUseSeparateSections(const llvm::Triple & Triple)7280b57cec5SDimitry Andric bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
7295f757f3fSDimitry Andric   return Triple.isPS();
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
isTLSDESCEnabled(const ToolChain & TC,const llvm::opt::ArgList & Args)732b3edf446SDimitry Andric bool tools::isTLSDESCEnabled(const ToolChain &TC,
733b3edf446SDimitry Andric                              const llvm::opt::ArgList &Args) {
734b3edf446SDimitry Andric   const llvm::Triple &Triple = TC.getEffectiveTriple();
735b3edf446SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_mtls_dialect_EQ);
736b3edf446SDimitry Andric   if (!A)
737b3edf446SDimitry Andric     return Triple.hasDefaultTLSDESC();
738b3edf446SDimitry Andric   StringRef V = A->getValue();
739b3edf446SDimitry Andric   bool SupportedArgument = false, EnableTLSDESC = false;
740b3edf446SDimitry Andric   bool Unsupported = !Triple.isOSBinFormatELF();
741b3edf446SDimitry Andric   if (Triple.isRISCV()) {
742b3edf446SDimitry Andric     SupportedArgument = V == "desc" || V == "trad";
743b3edf446SDimitry Andric     EnableTLSDESC = V == "desc";
744b3edf446SDimitry Andric   } else if (Triple.isX86()) {
745b3edf446SDimitry Andric     SupportedArgument = V == "gnu";
746b3edf446SDimitry Andric   } else {
747b3edf446SDimitry Andric     Unsupported = true;
748b3edf446SDimitry Andric   }
749b3edf446SDimitry Andric   if (Unsupported) {
750b3edf446SDimitry Andric     TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
751b3edf446SDimitry Andric         << A->getSpelling() << Triple.getTriple();
752b3edf446SDimitry Andric   } else if (!SupportedArgument) {
753b3edf446SDimitry Andric     TC.getDriver().Diag(diag::err_drv_unsupported_option_argument_for_target)
754b3edf446SDimitry Andric         << A->getSpelling() << V << Triple.getTriple();
755b3edf446SDimitry Andric   }
756b3edf446SDimitry Andric   return EnableTLSDESC;
757b3edf446SDimitry Andric }
758b3edf446SDimitry Andric 
addLTOOptions(const ToolChain & ToolChain,const ArgList & Args,ArgStringList & CmdArgs,const InputInfo & Output,const InputInfo & Input,bool IsThinLTO)7595ffd83dbSDimitry Andric void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
7600b57cec5SDimitry Andric                           ArgStringList &CmdArgs, const InputInfo &Output,
7610b57cec5SDimitry Andric                           const InputInfo &Input, bool IsThinLTO) {
762bdd1243dSDimitry Andric   const bool IsOSAIX = ToolChain.getTriple().isOSAIX();
76306c3fb27SDimitry Andric   const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN();
7645ffd83dbSDimitry Andric   const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
7655ffd83dbSDimitry Andric   const Driver &D = ToolChain.getDriver();
7667a6dacacSDimitry Andric   const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects);
7677a6dacacSDimitry Andric   const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto);
7685ffd83dbSDimitry Andric   if (llvm::sys::path::filename(Linker) != "ld.lld" &&
7695f757f3fSDimitry Andric       llvm::sys::path::stem(Linker) != "ld.lld" &&
7705f757f3fSDimitry Andric       !ToolChain.getTriple().isOSOpenBSD()) {
7715ffd83dbSDimitry Andric     // Tell the linker to load the plugin. This has to come before
772bdd1243dSDimitry Andric     // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to
773bdd1243dSDimitry Andric     // come before any -plugin-opt/-bplugin_opt that -Wl might forward.
774bdd1243dSDimitry Andric     const char *PluginPrefix = IsOSAIX ? "-bplugin:" : "";
775bdd1243dSDimitry Andric     const char *PluginName = IsOSAIX ? "/libLTO" : "/LLVMgold";
776bdd1243dSDimitry Andric 
777bdd1243dSDimitry Andric     if (!IsOSAIX)
7780b57cec5SDimitry Andric       CmdArgs.push_back("-plugin");
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric #if defined(_WIN32)
7810b57cec5SDimitry Andric     const char *Suffix = ".dll";
7820b57cec5SDimitry Andric #elif defined(__APPLE__)
7830b57cec5SDimitry Andric     const char *Suffix = ".dylib";
7840b57cec5SDimitry Andric #else
7850b57cec5SDimitry Andric     const char *Suffix = ".so";
7860b57cec5SDimitry Andric #endif
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric     SmallString<1024> Plugin;
789bdd1243dSDimitry Andric     llvm::sys::path::native(Twine(D.Dir) +
790bdd1243dSDimitry Andric                                 "/../" CLANG_INSTALL_LIBDIR_BASENAME +
791bdd1243dSDimitry Andric                                 PluginName + Suffix,
7920b57cec5SDimitry Andric                             Plugin);
793bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin));
7945f757f3fSDimitry Andric   } else {
7955f757f3fSDimitry Andric     // Tell LLD to find and use .llvm.lto section in regular relocatable object
7965f757f3fSDimitry Andric     // files
7977a6dacacSDimitry Andric     if (IsFatLTO)
7985f757f3fSDimitry Andric       CmdArgs.push_back("--fat-lto-objects");
799bdd1243dSDimitry Andric   }
800bdd1243dSDimitry Andric 
801bdd1243dSDimitry Andric   const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt=";
802bdd1243dSDimitry Andric   const char *ExtraDash = IsOSAIX ? "-" : "";
8035f757f3fSDimitry Andric   const char *ParallelismOpt = IsOSAIX ? "-threads=" : "jobs=";
804bdd1243dSDimitry Andric 
805bdd1243dSDimitry Andric   // Note, this solution is far from perfect, better to encode it into IR
806bdd1243dSDimitry Andric   // metadata, but this may not be worth it, since it looks like aranges is on
807bdd1243dSDimitry Andric   // the way out.
808bdd1243dSDimitry Andric   if (Args.hasArg(options::OPT_gdwarf_aranges)) {
809bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
810bdd1243dSDimitry Andric                                          "-generate-arange-section"));
8115ffd83dbSDimitry Andric   }
8120b57cec5SDimitry Andric 
813b3edf446SDimitry Andric   // Pass vector library arguments to LTO.
814b3edf446SDimitry Andric   Arg *ArgVecLib = Args.getLastArg(options::OPT_fveclib);
815b3edf446SDimitry Andric   if (ArgVecLib && ArgVecLib->getNumValues() == 1) {
816b3edf446SDimitry Andric     // Map the vector library names from clang front-end to opt front-end. The
817b3edf446SDimitry Andric     // values are taken from the TargetLibraryInfo class command line options.
818b3edf446SDimitry Andric     std::optional<StringRef> OptVal =
819b3edf446SDimitry Andric         llvm::StringSwitch<std::optional<StringRef>>(ArgVecLib->getValue())
820b3edf446SDimitry Andric             .Case("Accelerate", "Accelerate")
821b3edf446SDimitry Andric             .Case("LIBMVEC", "LIBMVEC-X86")
822b3edf446SDimitry Andric             .Case("MASSV", "MASSV")
823b3edf446SDimitry Andric             .Case("SVML", "SVML")
824b3edf446SDimitry Andric             .Case("SLEEF", "sleefgnuabi")
825b3edf446SDimitry Andric             .Case("Darwin_libsystem_m", "Darwin_libsystem_m")
826b3edf446SDimitry Andric             .Case("ArmPL", "ArmPL")
827b3edf446SDimitry Andric             .Case("none", "none")
828b3edf446SDimitry Andric             .Default(std::nullopt);
829b3edf446SDimitry Andric 
830b3edf446SDimitry Andric     if (OptVal)
831b3edf446SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(
832b3edf446SDimitry Andric           Twine(PluginOptPrefix) + "-vector-library=" + OptVal.value()));
833b3edf446SDimitry Andric   }
834b3edf446SDimitry Andric 
8350b57cec5SDimitry Andric   // Try to pass driver level flags relevant to LTO code generation down to
8360b57cec5SDimitry Andric   // the plugin.
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   // Handle flags for selecting CPU variants.
839349cc55cSDimitry Andric   std::string CPU = getCPUName(D, Args, ToolChain.getTriple());
8400b57cec5SDimitry Andric   if (!CPU.empty())
841bdd1243dSDimitry Andric     CmdArgs.push_back(
842bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU));
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
8455ffd83dbSDimitry Andric     // The optimization level matches
8465ffd83dbSDimitry Andric     // CompilerInvocation.cpp:getOptimizationLevel().
8470b57cec5SDimitry Andric     StringRef OOpt;
8480b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_O4) ||
8490b57cec5SDimitry Andric         A->getOption().matches(options::OPT_Ofast))
8500b57cec5SDimitry Andric       OOpt = "3";
8515ffd83dbSDimitry Andric     else if (A->getOption().matches(options::OPT_O)) {
8520b57cec5SDimitry Andric       OOpt = A->getValue();
8535ffd83dbSDimitry Andric       if (OOpt == "g")
8545ffd83dbSDimitry Andric         OOpt = "1";
8555ffd83dbSDimitry Andric       else if (OOpt == "s" || OOpt == "z")
8565ffd83dbSDimitry Andric         OOpt = "2";
8575ffd83dbSDimitry Andric     } else if (A->getOption().matches(options::OPT_O0))
8580b57cec5SDimitry Andric       OOpt = "0";
85906c3fb27SDimitry Andric     if (!OOpt.empty()) {
860bdd1243dSDimitry Andric       CmdArgs.push_back(
861bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "O" + OOpt));
86206c3fb27SDimitry Andric       if (IsAMDGCN)
86306c3fb27SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(Twine("--lto-CGO") + OOpt));
86406c3fb27SDimitry Andric     }
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric 
867bdd1243dSDimitry Andric   if (Args.hasArg(options::OPT_gsplit_dwarf))
868bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
869bdd1243dSDimitry Andric         Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo"));
8700b57cec5SDimitry Andric 
87106c3fb27SDimitry Andric   if (IsThinLTO && !IsOSAIX)
872bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto"));
87306c3fb27SDimitry Andric   else if (IsThinLTO && IsOSAIX)
87406c3fb27SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine("-bdbg:thinlto")));
87506c3fb27SDimitry Andric 
8765f757f3fSDimitry Andric   // Matrix intrinsic lowering happens at link time with ThinLTO. Enable
8775f757f3fSDimitry Andric   // LowerMatrixIntrinsicsPass, which is transitively called by
8785f757f3fSDimitry Andric   // buildThinLTODefaultPipeline under EnableMatrix.
8797a6dacacSDimitry Andric   if ((IsThinLTO || IsFatLTO || IsUnifiedLTO) &&
8807a6dacacSDimitry Andric         Args.hasArg(options::OPT_fenable_matrix))
8815f757f3fSDimitry Andric     CmdArgs.push_back(
8825f757f3fSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-matrix"));
8830b57cec5SDimitry Andric 
8845ffd83dbSDimitry Andric   StringRef Parallelism = getLTOParallelism(Args, D);
8855ffd83dbSDimitry Andric   if (!Parallelism.empty())
8865f757f3fSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
8875f757f3fSDimitry Andric                                          ParallelismOpt + Parallelism));
8885f757f3fSDimitry Andric 
8895f757f3fSDimitry Andric   // Pass down GlobalISel options.
8905f757f3fSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
8915f757f3fSDimitry Andric                                options::OPT_fno_global_isel)) {
8925f757f3fSDimitry Andric     // Parsing -fno-global-isel explicitly gives architectures that enable GISel
8935f757f3fSDimitry Andric     // by default a chance to disable it.
8945f757f3fSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
8955f757f3fSDimitry Andric         Twine(PluginOptPrefix) + "-global-isel=" +
8965f757f3fSDimitry Andric         (A->getOption().matches(options::OPT_fglobal_isel) ? "1" : "0")));
8975f757f3fSDimitry Andric   }
89881ad6265SDimitry Andric 
8990b57cec5SDimitry Andric   // If an explicit debugger tuning argument appeared, pass it along.
900bdd1243dSDimitry Andric   if (Arg *A =
901bdd1243dSDimitry Andric           Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
9020b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_glldb))
903bdd1243dSDimitry Andric       CmdArgs.push_back(
904bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=lldb"));
9050b57cec5SDimitry Andric     else if (A->getOption().matches(options::OPT_gsce))
906bdd1243dSDimitry Andric       CmdArgs.push_back(
907bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=sce"));
908fe6060f1SDimitry Andric     else if (A->getOption().matches(options::OPT_gdbx))
909bdd1243dSDimitry Andric       CmdArgs.push_back(
910bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=dbx"));
9110b57cec5SDimitry Andric     else
912bdd1243dSDimitry Andric       CmdArgs.push_back(
913bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=gdb"));
914bdd1243dSDimitry Andric   }
915bdd1243dSDimitry Andric 
916bdd1243dSDimitry Andric   if (IsOSAIX) {
91706c3fb27SDimitry Andric     if (!ToolChain.useIntegratedAs())
91806c3fb27SDimitry Andric       CmdArgs.push_back(
91906c3fb27SDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-no-integrated-as=1"));
92006c3fb27SDimitry Andric 
921bdd1243dSDimitry Andric     // On AIX, clang assumes strict-dwarf is true if any debug option is
922bdd1243dSDimitry Andric     // specified, unless it is told explicitly not to assume so.
923bdd1243dSDimitry Andric     Arg *A = Args.getLastArg(options::OPT_g_Group);
924bdd1243dSDimitry Andric     bool EnableDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
925bdd1243dSDimitry Andric                            !A->getOption().matches(options::OPT_ggdb0);
926bdd1243dSDimitry Andric     if (EnableDebugInfo && Args.hasFlag(options::OPT_gstrict_dwarf,
927bdd1243dSDimitry Andric                                         options::OPT_gno_strict_dwarf, true))
928bdd1243dSDimitry Andric       CmdArgs.push_back(
929bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-strict-dwarf=true"));
930bdd1243dSDimitry Andric 
93106c3fb27SDimitry Andric     for (const Arg *A : Args.filtered_reverse(options::OPT_mabi_EQ)) {
93206c3fb27SDimitry Andric       StringRef V = A->getValue();
93306c3fb27SDimitry Andric       if (V == "vec-default")
93406c3fb27SDimitry Andric         break;
93506c3fb27SDimitry Andric       if (V == "vec-extabi") {
936bdd1243dSDimitry Andric         CmdArgs.push_back(
937bdd1243dSDimitry Andric             Args.MakeArgString(Twine(PluginOptPrefix) + "-vec-extabi"));
93806c3fb27SDimitry Andric         break;
93906c3fb27SDimitry Andric       }
94006c3fb27SDimitry Andric     }
9410b57cec5SDimitry Andric   }
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   bool UseSeparateSections =
9440b57cec5SDimitry Andric       isUseSeparateSections(ToolChain.getEffectiveTriple());
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   if (Args.hasFlag(options::OPT_ffunction_sections,
947bdd1243dSDimitry Andric                    options::OPT_fno_function_sections, UseSeparateSections))
948bdd1243dSDimitry Andric     CmdArgs.push_back(
949bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=1"));
950bdd1243dSDimitry Andric   else if (Args.hasArg(options::OPT_fno_function_sections))
951bdd1243dSDimitry Andric     CmdArgs.push_back(
952bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=0"));
9530b57cec5SDimitry Andric 
95406c3fb27SDimitry Andric   bool DataSectionsTurnedOff = false;
9550b57cec5SDimitry Andric   if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
95606c3fb27SDimitry Andric                    UseSeparateSections)) {
957bdd1243dSDimitry Andric     CmdArgs.push_back(
958bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=1"));
95906c3fb27SDimitry Andric   } else if (Args.hasArg(options::OPT_fno_data_sections)) {
96006c3fb27SDimitry Andric     DataSectionsTurnedOff = true;
961bdd1243dSDimitry Andric     CmdArgs.push_back(
962bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=0"));
96306c3fb27SDimitry Andric   }
96406c3fb27SDimitry Andric 
96506c3fb27SDimitry Andric   if (Args.hasArg(options::OPT_mxcoff_roptr) ||
96606c3fb27SDimitry Andric       Args.hasArg(options::OPT_mno_xcoff_roptr)) {
96706c3fb27SDimitry Andric     bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr,
96806c3fb27SDimitry Andric                                  options::OPT_mno_xcoff_roptr, false);
96906c3fb27SDimitry Andric     StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr";
97006c3fb27SDimitry Andric 
97106c3fb27SDimitry Andric     if (!IsOSAIX)
97206c3fb27SDimitry Andric       D.Diag(diag::err_drv_unsupported_opt_for_target)
97306c3fb27SDimitry Andric           << OptStr << ToolChain.getTriple().str();
97406c3fb27SDimitry Andric 
97506c3fb27SDimitry Andric     if (HasRoptr) {
97606c3fb27SDimitry Andric       // The data sections option is on by default on AIX. We only need to error
97706c3fb27SDimitry Andric       // out when -fno-data-sections is specified explicitly to turn off data
97806c3fb27SDimitry Andric       // sections.
97906c3fb27SDimitry Andric       if (DataSectionsTurnedOff)
98006c3fb27SDimitry Andric         D.Diag(diag::err_roptr_requires_data_sections);
98106c3fb27SDimitry Andric 
98206c3fb27SDimitry Andric       CmdArgs.push_back(
98306c3fb27SDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + "-mxcoff-roptr"));
98406c3fb27SDimitry Andric     }
98506c3fb27SDimitry Andric   }
9860b57cec5SDimitry Andric 
98781ad6265SDimitry Andric   // Pass an option to enable split machine functions.
98881ad6265SDimitry Andric   if (auto *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
98981ad6265SDimitry Andric                                 options::OPT_fno_split_machine_functions)) {
99081ad6265SDimitry Andric     if (A->getOption().matches(options::OPT_fsplit_machine_functions))
991bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
992bdd1243dSDimitry Andric                                            "-split-machine-functions"));
99381ad6265SDimitry Andric   }
99481ad6265SDimitry Andric 
9950b57cec5SDimitry Andric   if (Arg *A = getLastProfileSampleUseArg(Args)) {
9960b57cec5SDimitry Andric     StringRef FName = A->getValue();
9970b57cec5SDimitry Andric     if (!llvm::sys::fs::exists(FName))
9985ffd83dbSDimitry Andric       D.Diag(diag::err_drv_no_such_file) << FName;
9990b57cec5SDimitry Andric     else
1000bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
1001bdd1243dSDimitry Andric                                            "sample-profile=" + FName));
10020b57cec5SDimitry Andric   }
10030b57cec5SDimitry Andric 
100406c3fb27SDimitry Andric   if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
1005bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
1006bdd1243dSDimitry Andric                                          "cs-profile-generate"));
10070b57cec5SDimitry Andric     if (CSPGOGenerateArg->getOption().matches(
10080b57cec5SDimitry Andric             options::OPT_fcs_profile_generate_EQ)) {
10090b57cec5SDimitry Andric       SmallString<128> Path(CSPGOGenerateArg->getValue());
10100b57cec5SDimitry Andric       llvm::sys::path::append(Path, "default_%m.profraw");
1011bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
1012bdd1243dSDimitry Andric                                            "cs-profile-path=" + Path));
10130b57cec5SDimitry Andric     } else
10140b57cec5SDimitry Andric       CmdArgs.push_back(
1015bdd1243dSDimitry Andric           Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
1016bdd1243dSDimitry Andric                              "cs-profile-path=default_%m.profraw"));
101706c3fb27SDimitry Andric   } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
10180b57cec5SDimitry Andric     SmallString<128> Path(
10190b57cec5SDimitry Andric         ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
10200b57cec5SDimitry Andric     if (Path.empty() || llvm::sys::fs::is_directory(Path))
10210b57cec5SDimitry Andric       llvm::sys::path::append(Path, "default.profdata");
1022bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
1023bdd1243dSDimitry Andric                                          "cs-profile-path=" + Path));
10240b57cec5SDimitry Andric   }
10250b57cec5SDimitry Andric 
1026bdd1243dSDimitry Andric   // This controls whether or not we perform JustMyCode instrumentation.
1027bdd1243dSDimitry Andric   if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) {
1028bdd1243dSDimitry Andric     if (ToolChain.getEffectiveTriple().isOSBinFormatELF())
1029bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
1030bdd1243dSDimitry Andric                                            "-enable-jmc-instrument"));
1031bdd1243dSDimitry Andric     else
1032bdd1243dSDimitry Andric       D.Diag(clang::diag::warn_drv_fjmc_for_elf_only);
1033bdd1243dSDimitry Andric   }
1034bdd1243dSDimitry Andric 
103506c3fb27SDimitry Andric   if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
103606c3fb27SDimitry Andric                    ToolChain.getTriple().hasDefaultEmulatedTLS())) {
103706c3fb27SDimitry Andric     CmdArgs.push_back(
103806c3fb27SDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls"));
1039cbe9438cSDimitry Andric   }
1040b3edf446SDimitry Andric   if (isTLSDESCEnabled(ToolChain, Args))
1041b3edf446SDimitry Andric     CmdArgs.push_back(
1042b3edf446SDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-tlsdesc"));
1043cbe9438cSDimitry Andric 
1044bdd1243dSDimitry Andric   if (Args.hasFlag(options::OPT_fstack_size_section,
1045bdd1243dSDimitry Andric                    options::OPT_fno_stack_size_section, false))
1046bdd1243dSDimitry Andric     CmdArgs.push_back(
1047bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "-stack-size-section"));
1048bdd1243dSDimitry Andric 
10490b57cec5SDimitry Andric   // Setup statistics file output.
10505ffd83dbSDimitry Andric   SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
10510b57cec5SDimitry Andric   if (!StatsFile.empty())
10520b57cec5SDimitry Andric     CmdArgs.push_back(
1053bdd1243dSDimitry Andric         Args.MakeArgString(Twine(PluginOptPrefix) + "stats-file=" + StatsFile));
10545ffd83dbSDimitry Andric 
1055bdd1243dSDimitry Andric   // Setup crash diagnostics dir.
1056bdd1243dSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
1057bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(
1058bdd1243dSDimitry Andric         Twine(PluginOptPrefix) + "-crash-diagnostics-dir=" + A->getValue()));
1059bdd1243dSDimitry Andric 
1060bdd1243dSDimitry Andric   addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true, PluginOptPrefix);
1061e8d8bef9SDimitry Andric 
1062e8d8bef9SDimitry Andric   // Handle remark diagnostics on screen options: '-Rpass-*'.
1063bdd1243dSDimitry Andric   renderRpassOptions(Args, CmdArgs, PluginOptPrefix);
1064e8d8bef9SDimitry Andric 
1065e8d8bef9SDimitry Andric   // Handle serialized remarks options: '-fsave-optimization-record'
1066e8d8bef9SDimitry Andric   // and '-foptimization-record-*'.
1067e8d8bef9SDimitry Andric   if (willEmitRemarks(Args))
1068e8d8bef9SDimitry Andric     renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input,
1069bdd1243dSDimitry Andric                          Output, PluginOptPrefix);
1070e8d8bef9SDimitry Andric 
1071e8d8bef9SDimitry Andric   // Handle remarks hotness/threshold related options.
1072bdd1243dSDimitry Andric   renderRemarksHotnessOptions(Args, CmdArgs, PluginOptPrefix);
1073e8d8bef9SDimitry Andric 
1074e8d8bef9SDimitry Andric   addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(),
1075bdd1243dSDimitry Andric                          /*IsLTO=*/true, PluginOptPrefix);
10760b57cec5SDimitry Andric }
10770b57cec5SDimitry Andric 
10785f757f3fSDimitry Andric /// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the
10795f757f3fSDimitry Andric /// LLVM C library for GPUs.
addOpenMPDeviceLibC(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)10805f757f3fSDimitry Andric static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args,
10815f757f3fSDimitry Andric                                 ArgStringList &CmdArgs) {
10825f757f3fSDimitry Andric   if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc))
10835f757f3fSDimitry Andric     return;
10845f757f3fSDimitry Andric 
10855f757f3fSDimitry Andric   // Check the resource directory for the LLVM libc GPU declarations. If it's
10865f757f3fSDimitry Andric   // found we can assume that LLVM was built with support for the GPU libc.
10875f757f3fSDimitry Andric   SmallString<256> LibCDecls(TC.getDriver().ResourceDir);
10885f757f3fSDimitry Andric   llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers",
10895f757f3fSDimitry Andric                           "llvm-libc-decls");
10905f757f3fSDimitry Andric   bool HasLibC = llvm::sys::fs::exists(LibCDecls) &&
10915f757f3fSDimitry Andric                  llvm::sys::fs::is_directory(LibCDecls);
10925f757f3fSDimitry Andric   if (Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC)) {
10935f757f3fSDimitry Andric     CmdArgs.push_back("-lcgpu");
10945f757f3fSDimitry Andric     CmdArgs.push_back("-lmgpu");
10955f757f3fSDimitry Andric   }
10965f757f3fSDimitry Andric }
10975f757f3fSDimitry Andric 
addOpenMPRuntimeLibraryPath(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)10982a66634dSDimitry Andric void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
10992a66634dSDimitry Andric                                         const ArgList &Args,
11002a66634dSDimitry Andric                                         ArgStringList &CmdArgs) {
11012a66634dSDimitry Andric   // Default to clang lib / lib64 folder, i.e. the same location as device
11022a66634dSDimitry Andric   // runtime.
11032a66634dSDimitry Andric   SmallString<256> DefaultLibPath =
11042a66634dSDimitry Andric       llvm::sys::path::parent_path(TC.getDriver().Dir);
1105bdd1243dSDimitry Andric   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
11062a66634dSDimitry Andric   CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
11072a66634dSDimitry Andric }
11082a66634dSDimitry Andric 
addArchSpecificRPath(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)11090b57cec5SDimitry Andric void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
11100b57cec5SDimitry Andric                                  ArgStringList &CmdArgs) {
11110b57cec5SDimitry Andric   if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
11125f757f3fSDimitry Andric                     options::OPT_fno_rtlib_add_rpath, false))
11130b57cec5SDimitry Andric     return;
11140b57cec5SDimitry Andric 
111506c3fb27SDimitry Andric   for (const auto &CandidateRPath : TC.getArchSpecificLibPaths()) {
11160b57cec5SDimitry Andric     if (TC.getVFS().exists(CandidateRPath)) {
11170b57cec5SDimitry Andric       CmdArgs.push_back("-rpath");
1118349cc55cSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(CandidateRPath));
11190b57cec5SDimitry Andric     }
11200b57cec5SDimitry Andric   }
112106c3fb27SDimitry Andric }
11220b57cec5SDimitry Andric 
addOpenMPRuntime(ArgStringList & CmdArgs,const ToolChain & TC,const ArgList & Args,bool ForceStaticHostRuntime,bool IsOffloadingHost,bool GompNeedsRT)11230b57cec5SDimitry Andric bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
1124a7dea167SDimitry Andric                              const ArgList &Args, bool ForceStaticHostRuntime,
1125a7dea167SDimitry Andric                              bool IsOffloadingHost, bool GompNeedsRT) {
11260b57cec5SDimitry Andric   if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
11270b57cec5SDimitry Andric                     options::OPT_fno_openmp, false))
11280b57cec5SDimitry Andric     return false;
11290b57cec5SDimitry Andric 
1130a7dea167SDimitry Andric   Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args);
1131a7dea167SDimitry Andric 
1132a7dea167SDimitry Andric   if (RTKind == Driver::OMPRT_Unknown)
1133a7dea167SDimitry Andric     // Already diagnosed.
1134a7dea167SDimitry Andric     return false;
1135a7dea167SDimitry Andric 
1136a7dea167SDimitry Andric   if (ForceStaticHostRuntime)
1137a7dea167SDimitry Andric     CmdArgs.push_back("-Bstatic");
1138a7dea167SDimitry Andric 
1139a7dea167SDimitry Andric   switch (RTKind) {
11400b57cec5SDimitry Andric   case Driver::OMPRT_OMP:
11410b57cec5SDimitry Andric     CmdArgs.push_back("-lomp");
11420b57cec5SDimitry Andric     break;
11430b57cec5SDimitry Andric   case Driver::OMPRT_GOMP:
11440b57cec5SDimitry Andric     CmdArgs.push_back("-lgomp");
11450b57cec5SDimitry Andric     break;
11460b57cec5SDimitry Andric   case Driver::OMPRT_IOMP5:
11470b57cec5SDimitry Andric     CmdArgs.push_back("-liomp5");
11480b57cec5SDimitry Andric     break;
11490b57cec5SDimitry Andric   case Driver::OMPRT_Unknown:
1150a7dea167SDimitry Andric     break;
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric 
1153a7dea167SDimitry Andric   if (ForceStaticHostRuntime)
1154a7dea167SDimitry Andric     CmdArgs.push_back("-Bdynamic");
1155a7dea167SDimitry Andric 
1156a7dea167SDimitry Andric   if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT)
1157a7dea167SDimitry Andric       CmdArgs.push_back("-lrt");
1158a7dea167SDimitry Andric 
11590b57cec5SDimitry Andric   if (IsOffloadingHost)
11600b57cec5SDimitry Andric     CmdArgs.push_back("-lomptarget");
11610b57cec5SDimitry Andric 
1162bdd1243dSDimitry Andric   if (IsOffloadingHost && !Args.hasArg(options::OPT_nogpulib))
116381ad6265SDimitry Andric     CmdArgs.push_back("-lomptarget.devicertl");
116481ad6265SDimitry Andric 
11655f757f3fSDimitry Andric   if (IsOffloadingHost)
11665f757f3fSDimitry Andric     addOpenMPDeviceLibC(TC, Args, CmdArgs);
11675f757f3fSDimitry Andric 
11680b57cec5SDimitry Andric   addArchSpecificRPath(TC, Args, CmdArgs);
11692a66634dSDimitry Andric   addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
11701fd87a68SDimitry Andric 
11710b57cec5SDimitry Andric   return true;
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric 
11745f757f3fSDimitry Andric /// Determines if --whole-archive is active in the list of arguments.
isWholeArchivePresent(const ArgList & Args)11755f757f3fSDimitry Andric static bool isWholeArchivePresent(const ArgList &Args) {
11765f757f3fSDimitry Andric   bool WholeArchiveActive = false;
11775f757f3fSDimitry Andric   for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
11785f757f3fSDimitry Andric     if (Arg) {
11795f757f3fSDimitry Andric       for (StringRef ArgValue : Arg->getValues()) {
11805f757f3fSDimitry Andric         if (ArgValue == "--whole-archive")
11815f757f3fSDimitry Andric           WholeArchiveActive = true;
11825f757f3fSDimitry Andric         if (ArgValue == "--no-whole-archive")
11835f757f3fSDimitry Andric           WholeArchiveActive = false;
11845f757f3fSDimitry Andric       }
11855f757f3fSDimitry Andric     }
11865f757f3fSDimitry Andric   }
11875f757f3fSDimitry Andric 
11885f757f3fSDimitry Andric   return WholeArchiveActive;
11895f757f3fSDimitry Andric }
11905f757f3fSDimitry Andric 
1191647cbc5dSDimitry Andric /// Determine if driver is invoked to create a shared object library (-static)
isSharedLinkage(const ArgList & Args)1192647cbc5dSDimitry Andric static bool isSharedLinkage(const ArgList &Args) {
1193647cbc5dSDimitry Andric   return Args.hasArg(options::OPT_shared);
1194647cbc5dSDimitry Andric }
1195647cbc5dSDimitry Andric 
1196647cbc5dSDimitry Andric /// Determine if driver is invoked to create a static object library (-shared)
isStaticLinkage(const ArgList & Args)1197647cbc5dSDimitry Andric static bool isStaticLinkage(const ArgList &Args) {
1198647cbc5dSDimitry Andric   return Args.hasArg(options::OPT_static);
1199647cbc5dSDimitry Andric }
1200647cbc5dSDimitry Andric 
12015f757f3fSDimitry Andric /// Add Fortran runtime libs for MSVC
addFortranRuntimeLibsMSVC(const ArgList & Args,llvm::opt::ArgStringList & CmdArgs)12025f757f3fSDimitry Andric static void addFortranRuntimeLibsMSVC(const ArgList &Args,
120381ad6265SDimitry Andric                                       llvm::opt::ArgStringList &CmdArgs) {
12045f757f3fSDimitry Andric   unsigned RTOptionID = options::OPT__SLASH_MT;
12055f757f3fSDimitry Andric   if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
12065f757f3fSDimitry Andric     RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
12075f757f3fSDimitry Andric                      .Case("static", options::OPT__SLASH_MT)
12085f757f3fSDimitry Andric                      .Case("static_dbg", options::OPT__SLASH_MTd)
12095f757f3fSDimitry Andric                      .Case("dll", options::OPT__SLASH_MD)
12105f757f3fSDimitry Andric                      .Case("dll_dbg", options::OPT__SLASH_MDd)
12115f757f3fSDimitry Andric                      .Default(options::OPT__SLASH_MT);
12125f757f3fSDimitry Andric   }
12135f757f3fSDimitry Andric   switch (RTOptionID) {
12145f757f3fSDimitry Andric   case options::OPT__SLASH_MT:
12155f757f3fSDimitry Andric     CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
12165f757f3fSDimitry Andric     break;
12175f757f3fSDimitry Andric   case options::OPT__SLASH_MTd:
12185f757f3fSDimitry Andric     CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
12195f757f3fSDimitry Andric     break;
12205f757f3fSDimitry Andric   case options::OPT__SLASH_MD:
12215f757f3fSDimitry Andric     CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
12225f757f3fSDimitry Andric     break;
12235f757f3fSDimitry Andric   case options::OPT__SLASH_MDd:
12245f757f3fSDimitry Andric     CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
12255f757f3fSDimitry Andric     break;
12265f757f3fSDimitry Andric   }
12275f757f3fSDimitry Andric }
12285f757f3fSDimitry Andric 
12295f757f3fSDimitry Andric // Add FortranMain runtime lib
addFortranMain(const ToolChain & TC,const ArgList & Args,llvm::opt::ArgStringList & CmdArgs)12305f757f3fSDimitry Andric static void addFortranMain(const ToolChain &TC, const ArgList &Args,
12315f757f3fSDimitry Andric                            llvm::opt::ArgStringList &CmdArgs) {
1232647cbc5dSDimitry Andric   // 0. Shared-library linkage
1233647cbc5dSDimitry Andric   // If we are attempting to link a library, we should not add
1234647cbc5dSDimitry Andric   // -lFortran_main.a to the link line, as the `main` symbol is not
1235647cbc5dSDimitry Andric   // required for a library and should also be provided by one of
1236647cbc5dSDimitry Andric   // the translation units of the code that this shared library
1237647cbc5dSDimitry Andric   // will be linked against eventually.
1238647cbc5dSDimitry Andric   if (isSharedLinkage(Args) || isStaticLinkage(Args)) {
1239647cbc5dSDimitry Andric     return;
1240647cbc5dSDimitry Andric   }
1241647cbc5dSDimitry Andric 
12425f757f3fSDimitry Andric   // 1. MSVC
124381ad6265SDimitry Andric   if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
12445f757f3fSDimitry Andric     addFortranRuntimeLibsMSVC(Args, CmdArgs);
12455f757f3fSDimitry Andric     return;
12465f757f3fSDimitry Andric   }
12475f757f3fSDimitry Andric 
12485f757f3fSDimitry Andric   // 2. GNU and similar
12497a6dacacSDimitry Andric   const Driver &D = TC.getDriver();
12507a6dacacSDimitry Andric   const char *FortranMainLinkFlag = "-lFortran_main";
12517a6dacacSDimitry Andric 
12527a6dacacSDimitry Andric   // Warn if the user added `-lFortran_main` - this library is an implementation
12537a6dacacSDimitry Andric   // detail of Flang and should be handled automaticaly by the driver.
12547a6dacacSDimitry Andric   for (const char *arg : CmdArgs) {
12557a6dacacSDimitry Andric     if (strncmp(arg, FortranMainLinkFlag, strlen(FortranMainLinkFlag)) == 0)
12567a6dacacSDimitry Andric       D.Diag(diag::warn_drv_deprecated_custom)
12577a6dacacSDimitry Andric           << FortranMainLinkFlag
12587a6dacacSDimitry Andric           << "see the Flang driver documentation for correct usage";
12597a6dacacSDimitry Andric   }
12607a6dacacSDimitry Andric 
12615f757f3fSDimitry Andric   // The --whole-archive option needs to be part of the link line to make
12625f757f3fSDimitry Andric   // sure that the main() function from Fortran_main.a is pulled in by the
12635f757f3fSDimitry Andric   // linker. However, it shouldn't be used if it's already active.
1264cb14a3feSDimitry Andric   // TODO: Find an equivalent of `--whole-archive` for Darwin and AIX.
1265cb14a3feSDimitry Andric   if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX() &&
1266cb14a3feSDimitry Andric       !TC.getTriple().isOSAIX()) {
12675f757f3fSDimitry Andric     CmdArgs.push_back("--whole-archive");
12687a6dacacSDimitry Andric     CmdArgs.push_back(FortranMainLinkFlag);
12695f757f3fSDimitry Andric     CmdArgs.push_back("--no-whole-archive");
12705f757f3fSDimitry Andric     return;
12715f757f3fSDimitry Andric   }
12725f757f3fSDimitry Andric 
12737a6dacacSDimitry Andric   CmdArgs.push_back(FortranMainLinkFlag);
12745f757f3fSDimitry Andric }
12755f757f3fSDimitry Andric 
12765f757f3fSDimitry Andric /// Add Fortran runtime libs
addFortranRuntimeLibs(const ToolChain & TC,const ArgList & Args,llvm::opt::ArgStringList & CmdArgs)12775f757f3fSDimitry Andric void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
12785f757f3fSDimitry Andric                                   llvm::opt::ArgStringList &CmdArgs) {
12795f757f3fSDimitry Andric   // 1. Link FortranMain
12805f757f3fSDimitry Andric   // FortranMain depends on FortranRuntime, so needs to be listed first. If
12815f757f3fSDimitry Andric   // -fno-fortran-main has been passed, skip linking Fortran_main.a
12825f757f3fSDimitry Andric   if (!Args.hasArg(options::OPT_no_fortran_main))
12835f757f3fSDimitry Andric     addFortranMain(TC, Args, CmdArgs);
12845f757f3fSDimitry Andric 
12855f757f3fSDimitry Andric   // 2. Link FortranRuntime and FortranDecimal
12865f757f3fSDimitry Andric   // These are handled earlier on Windows by telling the frontend driver to
12875f757f3fSDimitry Andric   // add the correct libraries to link against as dependents in the object
12885f757f3fSDimitry Andric   // file.
12895f757f3fSDimitry Andric   if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
129081ad6265SDimitry Andric     CmdArgs.push_back("-lFortranRuntime");
129181ad6265SDimitry Andric     CmdArgs.push_back("-lFortranDecimal");
129281ad6265SDimitry Andric   }
129381ad6265SDimitry Andric }
129481ad6265SDimitry Andric 
addFortranRuntimeLibraryPath(const ToolChain & TC,const llvm::opt::ArgList & Args,ArgStringList & CmdArgs)129581ad6265SDimitry Andric void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
129681ad6265SDimitry Andric                                          const llvm::opt::ArgList &Args,
129781ad6265SDimitry Andric                                          ArgStringList &CmdArgs) {
129881ad6265SDimitry Andric   // Default to the <driver-path>/../lib directory. This works fine on the
129981ad6265SDimitry Andric   // platforms that we have tested so far. We will probably have to re-fine
130081ad6265SDimitry Andric   // this in the future. In particular, on some platforms, we may need to use
130181ad6265SDimitry Andric   // lib64 instead of lib.
130281ad6265SDimitry Andric   SmallString<256> DefaultLibPath =
130381ad6265SDimitry Andric       llvm::sys::path::parent_path(TC.getDriver().Dir);
130481ad6265SDimitry Andric   llvm::sys::path::append(DefaultLibPath, "lib");
130581ad6265SDimitry Andric   if (TC.getTriple().isKnownWindowsMSVCEnvironment())
130681ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
130781ad6265SDimitry Andric   else
130881ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
130981ad6265SDimitry Andric }
131081ad6265SDimitry Andric 
addSanitizerRuntime(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer,bool IsShared,bool IsWhole)13110b57cec5SDimitry Andric static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
13120b57cec5SDimitry Andric                                 ArgStringList &CmdArgs, StringRef Sanitizer,
13130b57cec5SDimitry Andric                                 bool IsShared, bool IsWhole) {
13140b57cec5SDimitry Andric   // Wrap any static runtimes that must be forced into executable in
13150b57cec5SDimitry Andric   // whole-archive.
13160b57cec5SDimitry Andric   if (IsWhole) CmdArgs.push_back("--whole-archive");
13170b57cec5SDimitry Andric   CmdArgs.push_back(TC.getCompilerRTArgString(
13180b57cec5SDimitry Andric       Args, Sanitizer, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static));
13190b57cec5SDimitry Andric   if (IsWhole) CmdArgs.push_back("--no-whole-archive");
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   if (IsShared) {
13220b57cec5SDimitry Andric     addArchSpecificRPath(TC, Args, CmdArgs);
13230b57cec5SDimitry Andric   }
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric // Tries to use a file with the list of dynamic symbols that need to be exported
13270b57cec5SDimitry Andric // from the runtime library. Returns true if the file was found.
addSanitizerDynamicList(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer)13280b57cec5SDimitry Andric static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
13290b57cec5SDimitry Andric                                     ArgStringList &CmdArgs,
13300b57cec5SDimitry Andric                                     StringRef Sanitizer) {
13315f757f3fSDimitry Andric   bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
13325f757f3fSDimitry Andric 
13330b57cec5SDimitry Andric   // Solaris ld defaults to --export-dynamic behaviour but doesn't support
13340b57cec5SDimitry Andric   // the option, so don't try to pass it.
13355f757f3fSDimitry Andric   if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd)
13360b57cec5SDimitry Andric     return true;
13370b57cec5SDimitry Andric   SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
13380b57cec5SDimitry Andric   if (llvm::sys::fs::exists(SanRT + ".syms")) {
13390b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
13400b57cec5SDimitry Andric     return true;
13410b57cec5SDimitry Andric   }
13420b57cec5SDimitry Andric   return false;
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric 
addAsNeededOption(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs,bool as_needed)13455f757f3fSDimitry Andric void tools::addAsNeededOption(const ToolChain &TC,
13465f757f3fSDimitry Andric                               const llvm::opt::ArgList &Args,
13475f757f3fSDimitry Andric                               llvm::opt::ArgStringList &CmdArgs,
13485f757f3fSDimitry Andric                               bool as_needed) {
1349fe6060f1SDimitry Andric   assert(!TC.getTriple().isOSAIX() &&
1350fe6060f1SDimitry Andric          "AIX linker does not support any form of --as-needed option yet.");
13515f757f3fSDimitry Andric   bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
1352fe6060f1SDimitry Andric 
1353e8d8bef9SDimitry Andric   // While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases
1354e8d8bef9SDimitry Andric   // for the native forms -z ignore/-z record, they are missing in Illumos,
1355e8d8bef9SDimitry Andric   // so always use the native form.
13565f757f3fSDimitry Andric   // GNU ld doesn't support -z ignore/-z record, so don't use them even on
13575f757f3fSDimitry Andric   // Solaris.
13585f757f3fSDimitry Andric   if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) {
13595f757f3fSDimitry Andric     CmdArgs.push_back("-z");
13605f757f3fSDimitry Andric     CmdArgs.push_back(as_needed ? "ignore" : "record");
13615f757f3fSDimitry Andric   } else {
13625f757f3fSDimitry Andric     CmdArgs.push_back(as_needed ? "--as-needed" : "--no-as-needed");
13635f757f3fSDimitry Andric   }
1364e8d8bef9SDimitry Andric }
1365e8d8bef9SDimitry Andric 
linkSanitizerRuntimeDeps(const ToolChain & TC,const llvm::opt::ArgList & Args,ArgStringList & CmdArgs)13660b57cec5SDimitry Andric void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
13675f757f3fSDimitry Andric                                      const llvm::opt::ArgList &Args,
13680b57cec5SDimitry Andric                                      ArgStringList &CmdArgs) {
13690b57cec5SDimitry Andric   // Force linking against the system libraries sanitizers depends on
13700b57cec5SDimitry Andric   // (see PR15823 why this is necessary).
13715f757f3fSDimitry Andric   addAsNeededOption(TC, Args, CmdArgs, false);
13720b57cec5SDimitry Andric   // There's no libpthread or librt on RTEMS & Android.
13730b57cec5SDimitry Andric   if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
137406c3fb27SDimitry Andric       !TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
13750b57cec5SDimitry Andric     CmdArgs.push_back("-lpthread");
13760b57cec5SDimitry Andric     if (!TC.getTriple().isOSOpenBSD())
13770b57cec5SDimitry Andric       CmdArgs.push_back("-lrt");
13780b57cec5SDimitry Andric   }
13790b57cec5SDimitry Andric   CmdArgs.push_back("-lm");
13800b57cec5SDimitry Andric   // There's no libdl on all OSes.
1381fe6060f1SDimitry Andric   if (!TC.getTriple().isOSFreeBSD() && !TC.getTriple().isOSNetBSD() &&
13820b57cec5SDimitry Andric       !TC.getTriple().isOSOpenBSD() &&
13830b57cec5SDimitry Andric       TC.getTriple().getOS() != llvm::Triple::RTEMS)
13840b57cec5SDimitry Andric     CmdArgs.push_back("-ldl");
13850b57cec5SDimitry Andric   // Required for backtrace on some OSes
13860b57cec5SDimitry Andric   if (TC.getTriple().isOSFreeBSD() ||
138769ade1e0SDimitry Andric       TC.getTriple().isOSNetBSD() ||
138869ade1e0SDimitry Andric       TC.getTriple().isOSOpenBSD())
13890b57cec5SDimitry Andric     CmdArgs.push_back("-lexecinfo");
139081ad6265SDimitry Andric   // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl
139181ad6265SDimitry Andric   // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv
139281ad6265SDimitry Andric   // requirement.
139381ad6265SDimitry Andric   if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
139481ad6265SDimitry Andric       !TC.getTriple().isMusl())
139581ad6265SDimitry Andric     CmdArgs.push_back("-lresolv");
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric static void
collectSanitizerRuntimes(const ToolChain & TC,const ArgList & Args,SmallVectorImpl<StringRef> & SharedRuntimes,SmallVectorImpl<StringRef> & StaticRuntimes,SmallVectorImpl<StringRef> & NonWholeStaticRuntimes,SmallVectorImpl<StringRef> & HelperStaticRuntimes,SmallVectorImpl<StringRef> & RequiredSymbols)13990b57cec5SDimitry Andric collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
14000b57cec5SDimitry Andric                          SmallVectorImpl<StringRef> &SharedRuntimes,
14010b57cec5SDimitry Andric                          SmallVectorImpl<StringRef> &StaticRuntimes,
14020b57cec5SDimitry Andric                          SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
14030b57cec5SDimitry Andric                          SmallVectorImpl<StringRef> &HelperStaticRuntimes,
14040b57cec5SDimitry Andric                          SmallVectorImpl<StringRef> &RequiredSymbols) {
1405349cc55cSDimitry Andric   const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
14060b57cec5SDimitry Andric   // Collect shared runtimes.
14070b57cec5SDimitry Andric   if (SanArgs.needsSharedRt()) {
1408cb14a3feSDimitry Andric     if (SanArgs.needsAsanRt()) {
14090b57cec5SDimitry Andric       SharedRuntimes.push_back("asan");
14100b57cec5SDimitry Andric       if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
14110b57cec5SDimitry Andric         HelperStaticRuntimes.push_back("asan-preinit");
14120b57cec5SDimitry Andric     }
1413cb14a3feSDimitry Andric     if (SanArgs.needsMemProfRt()) {
1414e8d8bef9SDimitry Andric       SharedRuntimes.push_back("memprof");
1415e8d8bef9SDimitry Andric       if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
1416e8d8bef9SDimitry Andric         HelperStaticRuntimes.push_back("memprof-preinit");
1417e8d8bef9SDimitry Andric     }
1418cb14a3feSDimitry Andric     if (SanArgs.needsUbsanRt()) {
14190b57cec5SDimitry Andric       if (SanArgs.requiresMinimalRuntime())
14200b57cec5SDimitry Andric         SharedRuntimes.push_back("ubsan_minimal");
14210b57cec5SDimitry Andric       else
14220b57cec5SDimitry Andric         SharedRuntimes.push_back("ubsan_standalone");
14230b57cec5SDimitry Andric     }
1424cb14a3feSDimitry Andric     if (SanArgs.needsScudoRt()) {
1425bdd1243dSDimitry Andric       SharedRuntimes.push_back("scudo_standalone");
14260b57cec5SDimitry Andric     }
1427cb14a3feSDimitry Andric     if (SanArgs.needsTsanRt())
1428e8d8bef9SDimitry Andric       SharedRuntimes.push_back("tsan");
1429cb14a3feSDimitry Andric     if (SanArgs.needsHwasanRt()) {
1430fe6060f1SDimitry Andric       if (SanArgs.needsHwasanAliasesRt())
1431fe6060f1SDimitry Andric         SharedRuntimes.push_back("hwasan_aliases");
1432fe6060f1SDimitry Andric       else
14330b57cec5SDimitry Andric         SharedRuntimes.push_back("hwasan");
143481ad6265SDimitry Andric       if (!Args.hasArg(options::OPT_shared))
143581ad6265SDimitry Andric         HelperStaticRuntimes.push_back("hwasan-preinit");
14360b57cec5SDimitry Andric     }
1437fe6060f1SDimitry Andric   }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   // The stats_client library is also statically linked into DSOs.
1440cb14a3feSDimitry Andric   if (SanArgs.needsStatsRt())
14410b57cec5SDimitry Andric     StaticRuntimes.push_back("stats_client");
14420b57cec5SDimitry Andric 
14431fd87a68SDimitry Andric   // Always link the static runtime regardless of DSO or executable.
14441fd87a68SDimitry Andric   if (SanArgs.needsAsanRt())
14451fd87a68SDimitry Andric     HelperStaticRuntimes.push_back("asan_static");
14461fd87a68SDimitry Andric 
14470b57cec5SDimitry Andric   // Collect static runtimes.
14485ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_shared)) {
14495ffd83dbSDimitry Andric     // Don't link static runtimes into DSOs.
14500b57cec5SDimitry Andric     return;
14510b57cec5SDimitry Andric   }
14525ffd83dbSDimitry Andric 
14535ffd83dbSDimitry Andric   // Each static runtime that has a DSO counterpart above is excluded below,
14545ffd83dbSDimitry Andric   // but runtimes that exist only as static are not affected by needsSharedRt.
14555ffd83dbSDimitry Andric 
1456cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt()) {
14570b57cec5SDimitry Andric     StaticRuntimes.push_back("asan");
14580b57cec5SDimitry Andric     if (SanArgs.linkCXXRuntimes())
14590b57cec5SDimitry Andric       StaticRuntimes.push_back("asan_cxx");
14600b57cec5SDimitry Andric   }
14610b57cec5SDimitry Andric 
1462cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) {
1463e8d8bef9SDimitry Andric     StaticRuntimes.push_back("memprof");
1464e8d8bef9SDimitry Andric     if (SanArgs.linkCXXRuntimes())
1465e8d8bef9SDimitry Andric       StaticRuntimes.push_back("memprof_cxx");
1466e8d8bef9SDimitry Andric   }
1467e8d8bef9SDimitry Andric 
1468cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt()) {
1469fe6060f1SDimitry Andric     if (SanArgs.needsHwasanAliasesRt()) {
1470fe6060f1SDimitry Andric       StaticRuntimes.push_back("hwasan_aliases");
1471fe6060f1SDimitry Andric       if (SanArgs.linkCXXRuntimes())
1472fe6060f1SDimitry Andric         StaticRuntimes.push_back("hwasan_aliases_cxx");
1473fe6060f1SDimitry Andric     } else {
14740b57cec5SDimitry Andric       StaticRuntimes.push_back("hwasan");
14750b57cec5SDimitry Andric       if (SanArgs.linkCXXRuntimes())
14760b57cec5SDimitry Andric         StaticRuntimes.push_back("hwasan_cxx");
14770b57cec5SDimitry Andric     }
1478fe6060f1SDimitry Andric   }
1479cb14a3feSDimitry Andric   if (SanArgs.needsDfsanRt())
14800b57cec5SDimitry Andric     StaticRuntimes.push_back("dfsan");
1481cb14a3feSDimitry Andric   if (SanArgs.needsLsanRt())
14820b57cec5SDimitry Andric     StaticRuntimes.push_back("lsan");
1483cb14a3feSDimitry Andric   if (SanArgs.needsMsanRt()) {
14840b57cec5SDimitry Andric     StaticRuntimes.push_back("msan");
14850b57cec5SDimitry Andric     if (SanArgs.linkCXXRuntimes())
14860b57cec5SDimitry Andric       StaticRuntimes.push_back("msan_cxx");
14870b57cec5SDimitry Andric   }
1488cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) {
14890b57cec5SDimitry Andric     StaticRuntimes.push_back("tsan");
14900b57cec5SDimitry Andric     if (SanArgs.linkCXXRuntimes())
14910b57cec5SDimitry Andric       StaticRuntimes.push_back("tsan_cxx");
14920b57cec5SDimitry Andric   }
1493cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) {
14940b57cec5SDimitry Andric     if (SanArgs.requiresMinimalRuntime()) {
14950b57cec5SDimitry Andric       StaticRuntimes.push_back("ubsan_minimal");
14960b57cec5SDimitry Andric     } else {
14970b57cec5SDimitry Andric       StaticRuntimes.push_back("ubsan_standalone");
14980b57cec5SDimitry Andric       if (SanArgs.linkCXXRuntimes())
14990b57cec5SDimitry Andric         StaticRuntimes.push_back("ubsan_standalone_cxx");
15000b57cec5SDimitry Andric     }
15010b57cec5SDimitry Andric   }
1502cb14a3feSDimitry Andric   if (SanArgs.needsSafeStackRt()) {
15030b57cec5SDimitry Andric     NonWholeStaticRuntimes.push_back("safestack");
15040b57cec5SDimitry Andric     RequiredSymbols.push_back("__safestack_init");
15050b57cec5SDimitry Andric   }
1506cb14a3feSDimitry Andric   if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt())) {
1507cb14a3feSDimitry Andric     if (SanArgs.needsCfiRt())
15080b57cec5SDimitry Andric       StaticRuntimes.push_back("cfi");
1509cb14a3feSDimitry Andric     if (SanArgs.needsCfiDiagRt()) {
15100b57cec5SDimitry Andric       StaticRuntimes.push_back("cfi_diag");
15110b57cec5SDimitry Andric       if (SanArgs.linkCXXRuntimes())
15120b57cec5SDimitry Andric         StaticRuntimes.push_back("ubsan_standalone_cxx");
15130b57cec5SDimitry Andric     }
15145ffd83dbSDimitry Andric   }
1515cb14a3feSDimitry Andric   if (SanArgs.needsStatsRt()) {
15160b57cec5SDimitry Andric     NonWholeStaticRuntimes.push_back("stats");
15170b57cec5SDimitry Andric     RequiredSymbols.push_back("__sanitizer_stats_register");
15180b57cec5SDimitry Andric   }
1519cb14a3feSDimitry Andric   if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt()) {
1520bdd1243dSDimitry Andric     StaticRuntimes.push_back("scudo_standalone");
15210b57cec5SDimitry Andric     if (SanArgs.linkCXXRuntimes())
1522bdd1243dSDimitry Andric       StaticRuntimes.push_back("scudo_standalone_cxx");
15230b57cec5SDimitry Andric   }
15240b57cec5SDimitry Andric }
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric // Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
15270b57cec5SDimitry Andric // C runtime, etc). Returns true if sanitizer system deps need to be linked in.
addSanitizerRuntimes(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)15280b57cec5SDimitry Andric bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
15290b57cec5SDimitry Andric                                  ArgStringList &CmdArgs) {
1530cb14a3feSDimitry Andric   const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
15310b57cec5SDimitry Andric   SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
15320b57cec5SDimitry Andric       NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
1533cb14a3feSDimitry Andric   if (SanArgs.linkRuntimes()) {
15340b57cec5SDimitry Andric     collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
15350b57cec5SDimitry Andric                              NonWholeStaticRuntimes, HelperStaticRuntimes,
15360b57cec5SDimitry Andric                              RequiredSymbols);
1537cb14a3feSDimitry Andric   }
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric   // Inject libfuzzer dependencies.
1540a7dea167SDimitry Andric   if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
1541a7dea167SDimitry Andric       !Args.hasArg(options::OPT_shared)) {
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric     addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
1544e8d8bef9SDimitry Andric     if (SanArgs.needsFuzzerInterceptors())
1545e8d8bef9SDimitry Andric       addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer_interceptors", false,
1546e8d8bef9SDimitry Andric                           true);
1547e8d8bef9SDimitry Andric     if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) {
1548e8d8bef9SDimitry Andric       bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
1549e8d8bef9SDimitry Andric                                  !Args.hasArg(options::OPT_static);
1550e8d8bef9SDimitry Andric       if (OnlyLibstdcxxStatic)
1551e8d8bef9SDimitry Andric         CmdArgs.push_back("-Bstatic");
15520b57cec5SDimitry Andric       TC.AddCXXStdlibLibArgs(Args, CmdArgs);
1553e8d8bef9SDimitry Andric       if (OnlyLibstdcxxStatic)
1554e8d8bef9SDimitry Andric         CmdArgs.push_back("-Bdynamic");
1555e8d8bef9SDimitry Andric     }
15560b57cec5SDimitry Andric   }
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric   for (auto RT : SharedRuntimes)
15590b57cec5SDimitry Andric     addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false);
15600b57cec5SDimitry Andric   for (auto RT : HelperStaticRuntimes)
15610b57cec5SDimitry Andric     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
15620b57cec5SDimitry Andric   bool AddExportDynamic = false;
15630b57cec5SDimitry Andric   for (auto RT : StaticRuntimes) {
15640b57cec5SDimitry Andric     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
15650b57cec5SDimitry Andric     AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
15660b57cec5SDimitry Andric   }
15670b57cec5SDimitry Andric   for (auto RT : NonWholeStaticRuntimes) {
15680b57cec5SDimitry Andric     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false);
15690b57cec5SDimitry Andric     AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
15700b57cec5SDimitry Andric   }
15710b57cec5SDimitry Andric   for (auto S : RequiredSymbols) {
15720b57cec5SDimitry Andric     CmdArgs.push_back("-u");
15730b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(S));
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 
addXRayRuntime(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)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 
linkXRayRuntimeDeps(const ToolChain & TC,const llvm::opt::ArgList & Args,ArgStringList & CmdArgs)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 
areOptimizationsEnabled(const ArgList & Args)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 
SplitDebugName(const JobAction & JA,const ArgList & Args,const InputInfo & Input,const InputInfo & Output)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 
SplitDebugInfo(const ToolChain & TC,Compilation & C,const Tool & T,const JobAction & JA,const ArgList & Args,const InputInfo & Output,const char * OutFile)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.
claimNoWarnArgs(const ArgList & Args)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 
getLastCSProfileGenerateArg(const ArgList & Args)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 
getLastProfileUseArg(const ArgList & Args)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 
getLastProfileSampleUseArg(const ArgList & Args)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 
RelocationModelName(llvm::Reloc::Model Model)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>
ParsePICArgs(const ToolChain & ToolChain,const ArgList & Args)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.
ParseFunctionAlignment(const ToolChain & TC,const ArgList & Args)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 
addDebugInfoKind(ArgStringList & CmdArgs,llvm::codegenoptions::DebugInfoKind DebugInfoKind)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.
debugLevelToInfoKind(const Arg & A)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 
ParseDebugDefaultVersion(const ToolChain & TC,const ArgList & Args)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 
DwarfVersionNum(StringRef ArgValue)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 
getDwarfNArg(const ArgList & Args)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 
getDwarfVersion(const ToolChain & TC,const llvm::opt::ArgList & Args)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))
2088bdd1243dSDimitry Andric     if (int N = DwarfVersionNum(GDwarfN->getSpelling()))
2089bdd1243dSDimitry Andric       DwarfVersion = N;
2090bdd1243dSDimitry Andric   if (DwarfVersion == 0) {
2091bdd1243dSDimitry Andric     DwarfVersion = TC.GetDefaultDwarfVersion();
2092bdd1243dSDimitry Andric     assert(DwarfVersion && "toolchain default DWARF version must be nonzero");
2093bdd1243dSDimitry Andric   }
2094bdd1243dSDimitry Andric   return DwarfVersion;
2095bdd1243dSDimitry Andric }
2096bdd1243dSDimitry Andric 
AddAssemblerKPIC(const ToolChain & ToolChain,const ArgList & Args,ArgStringList & CmdArgs)20970b57cec5SDimitry Andric void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
20980b57cec5SDimitry Andric                              ArgStringList &CmdArgs) {
20990b57cec5SDimitry Andric   llvm::Reloc::Model RelocationModel;
21000b57cec5SDimitry Andric   unsigned PICLevel;
21010b57cec5SDimitry Andric   bool IsPIE;
21020b57cec5SDimitry Andric   std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args);
21030b57cec5SDimitry Andric 
21040b57cec5SDimitry Andric   if (RelocationModel != llvm::Reloc::Static)
21050b57cec5SDimitry Andric     CmdArgs.push_back("-KPIC");
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric /// Determine whether Objective-C automated reference counting is
21090b57cec5SDimitry Andric /// enabled.
isObjCAutoRefCount(const ArgList & Args)21100b57cec5SDimitry Andric bool tools::isObjCAutoRefCount(const ArgList &Args) {
21110b57cec5SDimitry Andric   return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
21150b57cec5SDimitry Andric 
getLibGccType(const ToolChain & TC,const Driver & D,const ArgList & Args)2116fe6060f1SDimitry Andric static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
2117fe6060f1SDimitry Andric                                 const ArgList &Args) {
21180b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_static_libgcc) ||
211981ad6265SDimitry Andric       Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie) ||
212081ad6265SDimitry Andric       // The Android NDK only provides libunwind.a, not libunwind.so.
212181ad6265SDimitry Andric       TC.getTriple().isAndroid())
21220b57cec5SDimitry Andric     return LibGccType::StaticLibGcc;
2123fe6060f1SDimitry Andric   if (Args.hasArg(options::OPT_shared_libgcc))
2124fe6060f1SDimitry Andric     return LibGccType::SharedLibGcc;
21250b57cec5SDimitry Andric   return LibGccType::UnspecifiedLibGcc;
21260b57cec5SDimitry Andric }
21270b57cec5SDimitry Andric 
21280b57cec5SDimitry Andric // Gcc adds libgcc arguments in various ways:
21290b57cec5SDimitry Andric //
21300b57cec5SDimitry Andric // gcc <none>:     -lgcc --as-needed -lgcc_s --no-as-needed
21310b57cec5SDimitry Andric // g++ <none>:                       -lgcc_s               -lgcc
21320b57cec5SDimitry Andric // gcc shared:                       -lgcc_s               -lgcc
21330b57cec5SDimitry Andric // g++ shared:                       -lgcc_s               -lgcc
21340b57cec5SDimitry Andric // gcc static:     -lgcc             -lgcc_eh
21350b57cec5SDimitry Andric // g++ static:     -lgcc             -lgcc_eh
21360b57cec5SDimitry Andric // gcc static-pie: -lgcc             -lgcc_eh
21370b57cec5SDimitry Andric // g++ static-pie: -lgcc             -lgcc_eh
21380b57cec5SDimitry Andric //
21390b57cec5SDimitry Andric // Also, certain targets need additional adjustments.
21400b57cec5SDimitry Andric 
AddUnwindLibrary(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)21410b57cec5SDimitry Andric static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
21420b57cec5SDimitry Andric                              ArgStringList &CmdArgs, const ArgList &Args) {
21430b57cec5SDimitry Andric   ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args);
214406c3fb27SDimitry Andric   // By default OHOS binaries are linked statically to libunwind.
214506c3fb27SDimitry Andric   if (TC.getTriple().isOHOSFamily() && UNW == ToolChain::UNW_CompilerRT) {
214606c3fb27SDimitry Andric     CmdArgs.push_back("-l:libunwind.a");
214706c3fb27SDimitry Andric     return;
214806c3fb27SDimitry Andric   }
214906c3fb27SDimitry Andric 
21500b57cec5SDimitry Andric   // Targets that don't use unwind libraries.
2151fe6060f1SDimitry Andric   if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) ||
2152fe6060f1SDimitry Andric       TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() ||
2153bdd1243dSDimitry Andric       TC.getTriple().isWindowsMSVCEnvironment() || UNW == ToolChain::UNW_None)
21540b57cec5SDimitry Andric     return;
21550b57cec5SDimitry Andric 
2156fe6060f1SDimitry Andric   LibGccType LGT = getLibGccType(TC, D, Args);
21570b57cec5SDimitry Andric   bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
215881ad6265SDimitry Andric                   (UNW == ToolChain::UNW_CompilerRT || !D.CCCIsCXX()) &&
2159fe6060f1SDimitry Andric                   !TC.getTriple().isAndroid() &&
2160fe6060f1SDimitry Andric                   !TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
21610b57cec5SDimitry Andric   if (AsNeeded)
21625f757f3fSDimitry Andric     addAsNeededOption(TC, Args, CmdArgs, true);
21630b57cec5SDimitry Andric 
21640b57cec5SDimitry Andric   switch (UNW) {
21650b57cec5SDimitry Andric   case ToolChain::UNW_None:
21660b57cec5SDimitry Andric     return;
21670b57cec5SDimitry Andric   case ToolChain::UNW_Libgcc: {
21680b57cec5SDimitry Andric     if (LGT == LibGccType::StaticLibGcc)
21690b57cec5SDimitry Andric       CmdArgs.push_back("-lgcc_eh");
21700b57cec5SDimitry Andric     else
21710b57cec5SDimitry Andric       CmdArgs.push_back("-lgcc_s");
21720b57cec5SDimitry Andric     break;
21730b57cec5SDimitry Andric   }
21740b57cec5SDimitry Andric   case ToolChain::UNW_CompilerRT:
2175fe6060f1SDimitry Andric     if (TC.getTriple().isOSAIX()) {
2176fe6060f1SDimitry Andric       // AIX only has libunwind as a shared library. So do not pass
2177fe6060f1SDimitry Andric       // anything in if -static is specified.
2178fe6060f1SDimitry Andric       if (LGT != LibGccType::StaticLibGcc)
2179fe6060f1SDimitry Andric         CmdArgs.push_back("-lunwind");
2180fe6060f1SDimitry Andric     } else if (LGT == LibGccType::StaticLibGcc) {
2181480093f4SDimitry Andric       CmdArgs.push_back("-l:libunwind.a");
218281ad6265SDimitry Andric     } else if (LGT == LibGccType::SharedLibGcc) {
218381ad6265SDimitry Andric       if (TC.getTriple().isOSCygMing())
21845ffd83dbSDimitry Andric         CmdArgs.push_back("-l:libunwind.dll.a");
2185480093f4SDimitry Andric       else
218681ad6265SDimitry Andric         CmdArgs.push_back("-l:libunwind.so");
218781ad6265SDimitry Andric     } else {
218881ad6265SDimitry Andric       // Let the linker choose between libunwind.so and libunwind.a
21895ffd83dbSDimitry Andric       // depending on what's available, and depending on the -static flag
21905ffd83dbSDimitry Andric       CmdArgs.push_back("-lunwind");
2191fe6060f1SDimitry Andric     }
21920b57cec5SDimitry Andric     break;
21930b57cec5SDimitry Andric   }
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric   if (AsNeeded)
21965f757f3fSDimitry Andric     addAsNeededOption(TC, Args, CmdArgs, false);
21970b57cec5SDimitry Andric }
21980b57cec5SDimitry Andric 
AddLibgcc(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)21990b57cec5SDimitry Andric static void AddLibgcc(const ToolChain &TC, const Driver &D,
22000b57cec5SDimitry Andric                       ArgStringList &CmdArgs, const ArgList &Args) {
2201fe6060f1SDimitry Andric   LibGccType LGT = getLibGccType(TC, D, Args);
220281ad6265SDimitry Andric   if (LGT == LibGccType::StaticLibGcc ||
220381ad6265SDimitry Andric       (LGT == LibGccType::UnspecifiedLibGcc && !D.CCCIsCXX()))
22040b57cec5SDimitry Andric     CmdArgs.push_back("-lgcc");
22050b57cec5SDimitry Andric   AddUnwindLibrary(TC, D, CmdArgs, Args);
220681ad6265SDimitry Andric   if (LGT == LibGccType::SharedLibGcc ||
220781ad6265SDimitry Andric       (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX()))
22080b57cec5SDimitry Andric     CmdArgs.push_back("-lgcc");
22090b57cec5SDimitry Andric }
22100b57cec5SDimitry Andric 
AddRunTimeLibs(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)22110b57cec5SDimitry Andric void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
22120b57cec5SDimitry Andric                            ArgStringList &CmdArgs, const ArgList &Args) {
22130b57cec5SDimitry Andric   // Make use of compiler-rt if --rtlib option is used
22140b57cec5SDimitry Andric   ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric   switch (RLT) {
22170b57cec5SDimitry Andric   case ToolChain::RLT_CompilerRT:
22180b57cec5SDimitry Andric     CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
22190b57cec5SDimitry Andric     AddUnwindLibrary(TC, D, CmdArgs, Args);
22200b57cec5SDimitry Andric     break;
22210b57cec5SDimitry Andric   case ToolChain::RLT_Libgcc:
22220b57cec5SDimitry Andric     // Make sure libgcc is not used under MSVC environment by default
22230b57cec5SDimitry Andric     if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
22240b57cec5SDimitry Andric       // Issue error diagnostic if libgcc is explicitly specified
22250b57cec5SDimitry Andric       // through command line as --rtlib option argument.
2226bdd1243dSDimitry Andric       Arg *A = Args.getLastArg(options::OPT_rtlib_EQ);
2227bdd1243dSDimitry Andric       if (A && A->getValue() != StringRef("platform")) {
22280b57cec5SDimitry Andric         TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
2229bdd1243dSDimitry Andric             << A->getValue() << "MSVC";
22300b57cec5SDimitry Andric       }
22310b57cec5SDimitry Andric     } else
22320b57cec5SDimitry Andric       AddLibgcc(TC, D, CmdArgs, Args);
22330b57cec5SDimitry Andric     break;
22340b57cec5SDimitry Andric   }
2235fe6060f1SDimitry Andric 
2236fe6060f1SDimitry Andric   // On Android, the unwinder uses dl_iterate_phdr (or one of
2237fe6060f1SDimitry Andric   // dl_unwind_find_exidx/__gnu_Unwind_Find_exidx on arm32) from libdl.so. For
2238fe6060f1SDimitry Andric   // statically-linked executables, these functions come from libc.a instead.
2239fe6060f1SDimitry Andric   if (TC.getTriple().isAndroid() && !Args.hasArg(options::OPT_static) &&
2240fe6060f1SDimitry Andric       !Args.hasArg(options::OPT_static_pie))
2241fe6060f1SDimitry Andric     CmdArgs.push_back("-ldl");
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric 
getStatsFileName(const llvm::opt::ArgList & Args,const InputInfo & Output,const InputInfo & Input,const Driver & D)22440b57cec5SDimitry Andric SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
22450b57cec5SDimitry Andric                                          const InputInfo &Output,
22460b57cec5SDimitry Andric                                          const InputInfo &Input,
22470b57cec5SDimitry Andric                                          const Driver &D) {
22480b57cec5SDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ);
224906c3fb27SDimitry Andric   if (!A && !D.CCPrintInternalStats)
22500b57cec5SDimitry Andric     return {};
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric   SmallString<128> StatsFile;
225306c3fb27SDimitry Andric   if (A) {
225406c3fb27SDimitry Andric     StringRef SaveStats = A->getValue();
22550b57cec5SDimitry Andric     if (SaveStats == "obj" && Output.isFilename()) {
22560b57cec5SDimitry Andric       StatsFile.assign(Output.getFilename());
22570b57cec5SDimitry Andric       llvm::sys::path::remove_filename(StatsFile);
22580b57cec5SDimitry Andric     } else if (SaveStats != "cwd") {
22590b57cec5SDimitry Andric       D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
22600b57cec5SDimitry Andric       return {};
22610b57cec5SDimitry Andric     }
22620b57cec5SDimitry Andric 
22630b57cec5SDimitry Andric     StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
22640b57cec5SDimitry Andric     llvm::sys::path::append(StatsFile, BaseName);
22650b57cec5SDimitry Andric     llvm::sys::path::replace_extension(StatsFile, "stats");
226606c3fb27SDimitry Andric   } else {
226706c3fb27SDimitry Andric     assert(D.CCPrintInternalStats);
226806c3fb27SDimitry Andric     StatsFile.assign(D.CCPrintInternalStatReportFilename.empty()
226906c3fb27SDimitry Andric                          ? "-"
227006c3fb27SDimitry Andric                          : D.CCPrintInternalStatReportFilename);
227106c3fb27SDimitry Andric   }
22720b57cec5SDimitry Andric   return StatsFile;
22730b57cec5SDimitry Andric }
22740b57cec5SDimitry Andric 
addMultilibFlag(bool Enabled,const StringRef Flag,Multilib::flags_list & Flags)227506c3fb27SDimitry Andric void tools::addMultilibFlag(bool Enabled, const StringRef Flag,
22760b57cec5SDimitry Andric                             Multilib::flags_list &Flags) {
227706c3fb27SDimitry Andric   assert(Flag.front() == '-');
227806c3fb27SDimitry Andric   if (Enabled) {
227906c3fb27SDimitry Andric     Flags.push_back(Flag.str());
228006c3fb27SDimitry Andric   } else {
228106c3fb27SDimitry Andric     Flags.push_back(("!" + Flag.substr(1)).str());
228206c3fb27SDimitry Andric   }
22830b57cec5SDimitry Andric }
22845ffd83dbSDimitry Andric 
addX86AlignBranchArgs(const Driver & D,const ArgList & Args,ArgStringList & CmdArgs,bool IsLTO,const StringRef PluginOptPrefix)22855ffd83dbSDimitry Andric void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
2286bdd1243dSDimitry Andric                                   ArgStringList &CmdArgs, bool IsLTO,
2287bdd1243dSDimitry Andric                                   const StringRef PluginOptPrefix) {
22885ffd83dbSDimitry Andric   auto addArg = [&, IsLTO](const Twine &Arg) {
22895ffd83dbSDimitry Andric     if (IsLTO) {
2290bdd1243dSDimitry Andric       assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
2291bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
22925ffd83dbSDimitry Andric     } else {
22935ffd83dbSDimitry Andric       CmdArgs.push_back("-mllvm");
22945ffd83dbSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Arg));
22955ffd83dbSDimitry Andric     }
22965ffd83dbSDimitry Andric   };
22975ffd83dbSDimitry Andric 
22985ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) {
22995ffd83dbSDimitry Andric     addArg(Twine("-x86-branches-within-32B-boundaries"));
23005ffd83dbSDimitry Andric   }
23015ffd83dbSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) {
23025ffd83dbSDimitry Andric     StringRef Value = A->getValue();
23035ffd83dbSDimitry Andric     unsigned Boundary;
23045ffd83dbSDimitry Andric     if (Value.getAsInteger(10, Boundary) || Boundary < 16 ||
23055ffd83dbSDimitry Andric         !llvm::isPowerOf2_64(Boundary)) {
23065ffd83dbSDimitry Andric       D.Diag(diag::err_drv_invalid_argument_to_option)
23075ffd83dbSDimitry Andric           << Value << A->getOption().getName();
23085ffd83dbSDimitry Andric     } else {
23095ffd83dbSDimitry Andric       addArg("-x86-align-branch-boundary=" + Twine(Boundary));
23105ffd83dbSDimitry Andric     }
23115ffd83dbSDimitry Andric   }
23125ffd83dbSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) {
23135ffd83dbSDimitry Andric     std::string AlignBranch;
23145ffd83dbSDimitry Andric     for (StringRef T : A->getValues()) {
23155ffd83dbSDimitry Andric       if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" &&
23165ffd83dbSDimitry Andric           T != "ret" && T != "indirect")
23175ffd83dbSDimitry Andric         D.Diag(diag::err_drv_invalid_malign_branch_EQ)
23185ffd83dbSDimitry Andric             << T << "fused, jcc, jmp, call, ret, indirect";
23195ffd83dbSDimitry Andric       if (!AlignBranch.empty())
23205ffd83dbSDimitry Andric         AlignBranch += '+';
23215ffd83dbSDimitry Andric       AlignBranch += T;
23225ffd83dbSDimitry Andric     }
23235ffd83dbSDimitry Andric     addArg("-x86-align-branch=" + Twine(AlignBranch));
23245ffd83dbSDimitry Andric   }
23255ffd83dbSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_mpad_max_prefix_size_EQ)) {
23265ffd83dbSDimitry Andric     StringRef Value = A->getValue();
23275ffd83dbSDimitry Andric     unsigned PrefixSize;
23285ffd83dbSDimitry Andric     if (Value.getAsInteger(10, PrefixSize)) {
23295ffd83dbSDimitry Andric       D.Diag(diag::err_drv_invalid_argument_to_option)
23305ffd83dbSDimitry Andric           << Value << A->getOption().getName();
23315ffd83dbSDimitry Andric     } else {
23325ffd83dbSDimitry Andric       addArg("-x86-pad-max-prefix-size=" + Twine(PrefixSize));
23335ffd83dbSDimitry Andric     }
23345ffd83dbSDimitry Andric   }
23355ffd83dbSDimitry Andric }
2336e8d8bef9SDimitry Andric 
2337349cc55cSDimitry Andric /// SDLSearch: Search for Static Device Library
2338349cc55cSDimitry Andric /// The search for SDL bitcode files is consistent with how static host
2339349cc55cSDimitry Andric /// libraries are discovered. That is, the -l option triggers a search for
2340349cc55cSDimitry Andric /// files in a set of directories called the LINKPATH. The host library search
2341349cc55cSDimitry Andric /// procedure looks for a specific filename in the LINKPATH.  The filename for
2342349cc55cSDimitry Andric /// a host library is lib<libname>.a or lib<libname>.so. For SDLs, there is an
2343349cc55cSDimitry Andric /// ordered-set of filenames that are searched. We call this ordered-set of
2344349cc55cSDimitry Andric /// filenames as SEARCH-ORDER. Since an SDL can either be device-type specific,
2345349cc55cSDimitry Andric /// architecture specific, or generic across all architectures, a naming
2346349cc55cSDimitry Andric /// convention and search order is used where the file name embeds the
2347349cc55cSDimitry Andric /// architecture name <arch-name> (nvptx or amdgcn) and the GPU device type
2348349cc55cSDimitry Andric /// <device-name> such as sm_30 and gfx906. <device-name> is absent in case of
2349349cc55cSDimitry Andric /// device-independent SDLs. To reduce congestion in host library directories,
2350349cc55cSDimitry Andric /// the search first looks for files in the “libdevice” subdirectory. SDLs that
2351349cc55cSDimitry Andric /// are bc files begin with the prefix “lib”.
2352349cc55cSDimitry Andric ///
2353349cc55cSDimitry Andric /// Machine-code SDLs can also be managed as an archive (*.a file). The
2354349cc55cSDimitry Andric /// convention has been to use the prefix “lib”. To avoid confusion with host
2355349cc55cSDimitry Andric /// archive libraries, we use prefix "libbc-" for the bitcode SDL archives.
2356349cc55cSDimitry Andric ///
SDLSearch(const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,const SmallVectorImpl<std::string> & LibraryPaths,StringRef Lib,StringRef Arch,StringRef Target,bool isBitCodeSDL)23575f757f3fSDimitry Andric static bool SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs,
2358349cc55cSDimitry Andric                       llvm::opt::ArgStringList &CC1Args,
23595f757f3fSDimitry Andric                       const SmallVectorImpl<std::string> &LibraryPaths,
23605f757f3fSDimitry Andric                       StringRef Lib, StringRef Arch, StringRef Target,
23615f757f3fSDimitry Andric                       bool isBitCodeSDL) {
2362349cc55cSDimitry Andric   SmallVector<std::string, 12> SDLs;
2363349cc55cSDimitry Andric 
2364349cc55cSDimitry Andric   std::string LibDeviceLoc = "/libdevice";
2365349cc55cSDimitry Andric   std::string LibBcPrefix = "/libbc-";
2366349cc55cSDimitry Andric   std::string LibPrefix = "/lib";
2367349cc55cSDimitry Andric 
2368349cc55cSDimitry Andric   if (isBitCodeSDL) {
2369349cc55cSDimitry Andric     // SEARCH-ORDER for Bitcode SDLs:
2370349cc55cSDimitry Andric     //       libdevice/libbc-<libname>-<arch-name>-<device-type>.a
2371349cc55cSDimitry Andric     //       libbc-<libname>-<arch-name>-<device-type>.a
2372349cc55cSDimitry Andric     //       libdevice/libbc-<libname>-<arch-name>.a
2373349cc55cSDimitry Andric     //       libbc-<libname>-<arch-name>.a
2374349cc55cSDimitry Andric     //       libdevice/libbc-<libname>.a
2375349cc55cSDimitry Andric     //       libbc-<libname>.a
2376349cc55cSDimitry Andric     //       libdevice/lib<libname>-<arch-name>-<device-type>.bc
2377349cc55cSDimitry Andric     //       lib<libname>-<arch-name>-<device-type>.bc
2378349cc55cSDimitry Andric     //       libdevice/lib<libname>-<arch-name>.bc
2379349cc55cSDimitry Andric     //       lib<libname>-<arch-name>.bc
2380349cc55cSDimitry Andric     //       libdevice/lib<libname>.bc
2381349cc55cSDimitry Andric     //       lib<libname>.bc
2382349cc55cSDimitry Andric 
2383349cc55cSDimitry Andric     for (StringRef Base : {LibBcPrefix, LibPrefix}) {
2384349cc55cSDimitry Andric       const auto *Ext = Base.contains(LibBcPrefix) ? ".a" : ".bc";
2385349cc55cSDimitry Andric 
2386349cc55cSDimitry Andric       for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
2387349cc55cSDimitry Andric                           Twine(Lib + "-" + Arch).str(), Twine(Lib).str()}) {
2388349cc55cSDimitry Andric         SDLs.push_back(Twine(LibDeviceLoc + Base + Suffix + Ext).str());
2389349cc55cSDimitry Andric         SDLs.push_back(Twine(Base + Suffix + Ext).str());
2390349cc55cSDimitry Andric       }
2391349cc55cSDimitry Andric     }
2392349cc55cSDimitry Andric   } else {
2393349cc55cSDimitry Andric     // SEARCH-ORDER for Machine-code SDLs:
2394349cc55cSDimitry Andric     //    libdevice/lib<libname>-<arch-name>-<device-type>.a
2395349cc55cSDimitry Andric     //    lib<libname>-<arch-name>-<device-type>.a
2396349cc55cSDimitry Andric     //    libdevice/lib<libname>-<arch-name>.a
2397349cc55cSDimitry Andric     //    lib<libname>-<arch-name>.a
2398349cc55cSDimitry Andric 
2399349cc55cSDimitry Andric     const auto *Ext = ".a";
2400349cc55cSDimitry Andric 
2401349cc55cSDimitry Andric     for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
2402349cc55cSDimitry Andric                         Twine(Lib + "-" + Arch).str()}) {
2403349cc55cSDimitry Andric       SDLs.push_back(Twine(LibDeviceLoc + LibPrefix + Suffix + Ext).str());
2404349cc55cSDimitry Andric       SDLs.push_back(Twine(LibPrefix + Suffix + Ext).str());
2405349cc55cSDimitry Andric     }
2406349cc55cSDimitry Andric   }
2407349cc55cSDimitry Andric 
2408349cc55cSDimitry Andric   // The CUDA toolchain does not use a global device llvm-link before the LLVM
2409349cc55cSDimitry Andric   // backend generates ptx. So currently, the use of bitcode SDL for nvptx is
2410349cc55cSDimitry Andric   // only possible with post-clang-cc1 linking. Clang cc1 has a feature that
2411349cc55cSDimitry Andric   // will link libraries after clang compilation while the LLVM IR is still in
2412349cc55cSDimitry Andric   // memory. This utilizes a clang cc1 option called “-mlink-builtin-bitcode”.
2413349cc55cSDimitry Andric   // This is a clang -cc1 option that is generated by the clang driver. The
2414349cc55cSDimitry Andric   // option value must a full path to an existing file.
2415349cc55cSDimitry Andric   bool FoundSDL = false;
2416349cc55cSDimitry Andric   for (auto LPath : LibraryPaths) {
2417349cc55cSDimitry Andric     for (auto SDL : SDLs) {
2418349cc55cSDimitry Andric       auto FullName = Twine(LPath + SDL).str();
2419349cc55cSDimitry Andric       if (llvm::sys::fs::exists(FullName)) {
2420349cc55cSDimitry Andric         CC1Args.push_back(DriverArgs.MakeArgString(FullName));
2421349cc55cSDimitry Andric         FoundSDL = true;
2422349cc55cSDimitry Andric         break;
2423349cc55cSDimitry Andric       }
2424349cc55cSDimitry Andric     }
2425349cc55cSDimitry Andric     if (FoundSDL)
2426349cc55cSDimitry Andric       break;
2427349cc55cSDimitry Andric   }
2428349cc55cSDimitry Andric   return FoundSDL;
2429349cc55cSDimitry Andric }
2430349cc55cSDimitry Andric 
2431349cc55cSDimitry Andric /// Search if a user provided archive file lib<libname>.a exists in any of
2432349cc55cSDimitry Andric /// the library paths. If so, add a new command to clang-offload-bundler to
2433349cc55cSDimitry Andric /// unbundle this archive and create a temporary device specific archive. Name
2434bdd1243dSDimitry Andric /// of this SDL is passed to the llvm-link tool.
GetSDLFromOffloadArchive(Compilation & C,const Driver & D,const Tool & T,const JobAction & JA,const InputInfoList & Inputs,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,const SmallVectorImpl<std::string> & LibraryPaths,StringRef Lib,StringRef Arch,StringRef Target,bool isBitCodeSDL)24355f757f3fSDimitry Andric static void GetSDLFromOffloadArchive(
2436349cc55cSDimitry Andric     Compilation &C, const Driver &D, const Tool &T, const JobAction &JA,
2437349cc55cSDimitry Andric     const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs,
24385f757f3fSDimitry Andric     llvm::opt::ArgStringList &CC1Args,
24395f757f3fSDimitry Andric     const SmallVectorImpl<std::string> &LibraryPaths, StringRef Lib,
24405f757f3fSDimitry Andric     StringRef Arch, StringRef Target, bool isBitCodeSDL) {
2441349cc55cSDimitry Andric 
2442349cc55cSDimitry Andric   // We don't support bitcode archive bundles for nvptx
2443349cc55cSDimitry Andric   if (isBitCodeSDL && Arch.contains("nvptx"))
24445f757f3fSDimitry Andric     return;
2445349cc55cSDimitry Andric 
2446349cc55cSDimitry Andric   bool FoundAOB = false;
2447349cc55cSDimitry Andric   std::string ArchiveOfBundles;
2448349cc55cSDimitry Andric 
244981ad6265SDimitry Andric   llvm::Triple Triple(D.getTargetTriple());
245081ad6265SDimitry Andric   bool IsMSVC = Triple.isWindowsMSVCEnvironment();
2451bdd1243dSDimitry Andric   auto Ext = IsMSVC ? ".lib" : ".a";
24525f757f3fSDimitry Andric   if (!Lib.starts_with(":") && !Lib.starts_with("-l")) {
2453bdd1243dSDimitry Andric     if (llvm::sys::fs::exists(Lib)) {
2454bdd1243dSDimitry Andric       ArchiveOfBundles = Lib;
2455bdd1243dSDimitry Andric       FoundAOB = true;
245681ad6265SDimitry Andric     }
2457bdd1243dSDimitry Andric   } else {
2458647cbc5dSDimitry Andric     Lib.consume_front("-l");
2459bdd1243dSDimitry Andric     for (auto LPath : LibraryPaths) {
2460bdd1243dSDimitry Andric       ArchiveOfBundles.clear();
24615f757f3fSDimitry Andric       auto LibFile = (Lib.starts_with(":") ? Lib.drop_front()
24625f757f3fSDimitry Andric                       : IsMSVC             ? Lib + Ext
24635f757f3fSDimitry Andric                                            : "lib" + Lib + Ext)
2464bdd1243dSDimitry Andric                          .str();
2465bdd1243dSDimitry Andric       for (auto Prefix : {"/libdevice/", "/"}) {
2466bdd1243dSDimitry Andric         auto AOB = Twine(LPath + Prefix + LibFile).str();
2467349cc55cSDimitry Andric         if (llvm::sys::fs::exists(AOB)) {
2468349cc55cSDimitry Andric           ArchiveOfBundles = AOB;
2469349cc55cSDimitry Andric           FoundAOB = true;
2470349cc55cSDimitry Andric           break;
2471349cc55cSDimitry Andric         }
2472349cc55cSDimitry Andric       }
2473bdd1243dSDimitry Andric       if (FoundAOB)
2474bdd1243dSDimitry Andric         break;
2475bdd1243dSDimitry Andric     }
2476bdd1243dSDimitry Andric   }
2477349cc55cSDimitry Andric 
2478349cc55cSDimitry Andric   if (!FoundAOB)
24795f757f3fSDimitry Andric     return;
2480bdd1243dSDimitry Andric 
2481bdd1243dSDimitry Andric   llvm::file_magic Magic;
2482bdd1243dSDimitry Andric   auto EC = llvm::identify_magic(ArchiveOfBundles, Magic);
2483bdd1243dSDimitry Andric   if (EC || Magic != llvm::file_magic::archive)
24845f757f3fSDimitry Andric     return;
2485349cc55cSDimitry Andric 
2486349cc55cSDimitry Andric   StringRef Prefix = isBitCodeSDL ? "libbc-" : "lib";
2487bdd1243dSDimitry Andric   std::string OutputLib =
2488bdd1243dSDimitry Andric       D.GetTemporaryPath(Twine(Prefix + llvm::sys::path::filename(Lib) + "-" +
2489bdd1243dSDimitry Andric                                Arch + "-" + Target)
2490bdd1243dSDimitry Andric                              .str(),
2491bdd1243dSDimitry Andric                          "a");
2492349cc55cSDimitry Andric 
249304eeddc0SDimitry Andric   C.addTempFile(C.getArgs().MakeArgString(OutputLib));
2494349cc55cSDimitry Andric 
2495349cc55cSDimitry Andric   ArgStringList CmdArgs;
2496349cc55cSDimitry Andric   SmallString<128> DeviceTriple;
2497349cc55cSDimitry Andric   DeviceTriple += Action::GetOffloadKindName(JA.getOffloadingDeviceKind());
2498349cc55cSDimitry Andric   DeviceTriple += '-';
2499349cc55cSDimitry Andric   std::string NormalizedTriple = T.getToolChain().getTriple().normalize();
2500349cc55cSDimitry Andric   DeviceTriple += NormalizedTriple;
2501349cc55cSDimitry Andric   if (!Target.empty()) {
2502349cc55cSDimitry Andric     DeviceTriple += '-';
2503349cc55cSDimitry Andric     DeviceTriple += Target;
2504349cc55cSDimitry Andric   }
2505349cc55cSDimitry Andric 
2506349cc55cSDimitry Andric   std::string UnbundleArg("-unbundle");
2507349cc55cSDimitry Andric   std::string TypeArg("-type=a");
250881ad6265SDimitry Andric   std::string InputArg("-input=" + ArchiveOfBundles);
2509349cc55cSDimitry Andric   std::string OffloadArg("-targets=" + std::string(DeviceTriple));
251081ad6265SDimitry Andric   std::string OutputArg("-output=" + OutputLib);
2511349cc55cSDimitry Andric 
2512349cc55cSDimitry Andric   const char *UBProgram = DriverArgs.MakeArgString(
2513349cc55cSDimitry Andric       T.getToolChain().GetProgramPath("clang-offload-bundler"));
2514349cc55cSDimitry Andric 
2515349cc55cSDimitry Andric   ArgStringList UBArgs;
251604eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(UnbundleArg));
251704eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(TypeArg));
251804eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(InputArg));
251904eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(OffloadArg));
252004eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(OutputArg));
2521349cc55cSDimitry Andric 
2522349cc55cSDimitry Andric   // Add this flag to not exit from clang-offload-bundler if no compatible
2523349cc55cSDimitry Andric   // code object is found in heterogenous archive library.
2524349cc55cSDimitry Andric   std::string AdditionalArgs("-allow-missing-bundles");
252504eeddc0SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(AdditionalArgs));
2526349cc55cSDimitry Andric 
252781ad6265SDimitry Andric   // Add this flag to treat hip and hipv4 offload kinds as compatible with
252881ad6265SDimitry Andric   // openmp offload kind while extracting code objects from a heterogenous
252981ad6265SDimitry Andric   // archive library. Vice versa is also considered compatible.
253081ad6265SDimitry Andric   std::string HipCompatibleArgs("-hip-openmp-compatible");
253181ad6265SDimitry Andric   UBArgs.push_back(C.getArgs().MakeArgString(HipCompatibleArgs));
253281ad6265SDimitry Andric 
2533349cc55cSDimitry Andric   C.addCommand(std::make_unique<Command>(
2534349cc55cSDimitry Andric       JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs,
253504eeddc0SDimitry Andric       InputInfo(&JA, C.getArgs().MakeArgString(OutputLib))));
2536349cc55cSDimitry Andric 
2537349cc55cSDimitry Andric   CC1Args.push_back(DriverArgs.MakeArgString(OutputLib));
2538349cc55cSDimitry Andric 
25395f757f3fSDimitry Andric   return;
2540349cc55cSDimitry Andric }
2541349cc55cSDimitry Andric 
2542349cc55cSDimitry Andric // Wrapper function used by driver for adding SDLs during link phase.
AddStaticDeviceLibsLinking(Compilation & C,const Tool & T,const JobAction & JA,const InputInfoList & Inputs,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef Arch,StringRef Target,bool isBitCodeSDL)2543349cc55cSDimitry Andric void tools::AddStaticDeviceLibsLinking(Compilation &C, const Tool &T,
2544349cc55cSDimitry Andric                                        const JobAction &JA,
2545349cc55cSDimitry Andric                                        const InputInfoList &Inputs,
2546349cc55cSDimitry Andric                                        const llvm::opt::ArgList &DriverArgs,
2547349cc55cSDimitry Andric                                        llvm::opt::ArgStringList &CC1Args,
2548349cc55cSDimitry Andric                                        StringRef Arch, StringRef Target,
25495f757f3fSDimitry Andric                                        bool isBitCodeSDL) {
2550349cc55cSDimitry Andric   AddStaticDeviceLibs(&C, &T, &JA, &Inputs, C.getDriver(), DriverArgs, CC1Args,
25515f757f3fSDimitry Andric                       Arch, Target, isBitCodeSDL);
2552349cc55cSDimitry Andric }
2553349cc55cSDimitry Andric 
2554349cc55cSDimitry Andric // User defined Static Device Libraries(SDLs) can be passed to clang for
2555349cc55cSDimitry Andric // offloading GPU compilers. Like static host libraries, the use of a SDL is
2556349cc55cSDimitry Andric // specified with the -l command line option. The primary difference between
2557349cc55cSDimitry Andric // host and SDLs is the filenames for SDLs (refer SEARCH-ORDER for Bitcode SDLs
2558349cc55cSDimitry Andric // and SEARCH-ORDER for Machine-code SDLs for the naming convention).
2559349cc55cSDimitry Andric // SDLs are of following types:
2560349cc55cSDimitry Andric //
2561349cc55cSDimitry Andric // * Bitcode SDLs: They can either be a *.bc file or an archive of *.bc files.
2562349cc55cSDimitry Andric //           For NVPTX, these libraries are post-clang linked following each
2563349cc55cSDimitry Andric //           compilation. For AMDGPU, these libraries are linked one time
2564349cc55cSDimitry Andric //           during the application link phase.
2565349cc55cSDimitry Andric //
2566bdd1243dSDimitry Andric // * Machine-code SDLs: They are archive files. For AMDGPU, the process for
2567bdd1243dSDimitry Andric //           machine code SDLs is still in development. But they will be linked
2568bdd1243dSDimitry Andric //           by the LLVM tool lld.
2569349cc55cSDimitry Andric //
2570349cc55cSDimitry Andric // * Bundled objects that contain both host and device codes: Bundled objects
2571349cc55cSDimitry Andric //           may also contain library code compiled from source. For NVPTX, the
2572349cc55cSDimitry Andric //           bundle contains cubin. For AMDGPU, the bundle contains bitcode.
2573349cc55cSDimitry Andric //
2574349cc55cSDimitry Andric // For Bitcode and Machine-code SDLs, current compiler toolchains hardcode the
2575349cc55cSDimitry Andric // inclusion of specific SDLs such as math libraries and the OpenMP device
2576349cc55cSDimitry Andric // library libomptarget.
AddStaticDeviceLibs(Compilation * C,const Tool * T,const JobAction * JA,const InputInfoList * Inputs,const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef Arch,StringRef Target,bool isBitCodeSDL)2577349cc55cSDimitry Andric void tools::AddStaticDeviceLibs(Compilation *C, const Tool *T,
2578349cc55cSDimitry Andric                                 const JobAction *JA,
2579349cc55cSDimitry Andric                                 const InputInfoList *Inputs, const Driver &D,
2580349cc55cSDimitry Andric                                 const llvm::opt::ArgList &DriverArgs,
2581349cc55cSDimitry Andric                                 llvm::opt::ArgStringList &CC1Args,
2582349cc55cSDimitry Andric                                 StringRef Arch, StringRef Target,
25835f757f3fSDimitry Andric                                 bool isBitCodeSDL) {
2584349cc55cSDimitry Andric 
2585349cc55cSDimitry Andric   SmallVector<std::string, 8> LibraryPaths;
2586349cc55cSDimitry Andric   // Add search directories from LIBRARY_PATH env variable
2587bdd1243dSDimitry Andric   std::optional<std::string> LibPath =
2588349cc55cSDimitry Andric       llvm::sys::Process::GetEnv("LIBRARY_PATH");
2589349cc55cSDimitry Andric   if (LibPath) {
2590349cc55cSDimitry Andric     SmallVector<StringRef, 8> Frags;
2591349cc55cSDimitry Andric     const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
2592349cc55cSDimitry Andric     llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
2593349cc55cSDimitry Andric     for (StringRef Path : Frags)
2594349cc55cSDimitry Andric       LibraryPaths.emplace_back(Path.trim());
2595349cc55cSDimitry Andric   }
2596349cc55cSDimitry Andric 
2597349cc55cSDimitry Andric   // Add directories from user-specified -L options
2598349cc55cSDimitry Andric   for (std::string Search_Dir : DriverArgs.getAllArgValues(options::OPT_L))
2599349cc55cSDimitry Andric     LibraryPaths.emplace_back(Search_Dir);
2600349cc55cSDimitry Andric 
2601349cc55cSDimitry Andric   // Add path to lib-debug folders
2602349cc55cSDimitry Andric   SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
2603bdd1243dSDimitry Andric   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
2604349cc55cSDimitry Andric   LibraryPaths.emplace_back(DefaultLibPath.c_str());
2605349cc55cSDimitry Andric 
2606349cc55cSDimitry Andric   // Build list of Static Device Libraries SDLs specified by -l option
2607349cc55cSDimitry Andric   llvm::SmallSet<std::string, 16> SDLNames;
2608349cc55cSDimitry Andric   static const StringRef HostOnlyArchives[] = {
2609349cc55cSDimitry Andric       "omp", "cudart", "m", "gcc", "gcc_s", "pthread", "hip_hcc"};
2610349cc55cSDimitry Andric   for (auto SDLName : DriverArgs.getAllArgValues(options::OPT_l)) {
26115f757f3fSDimitry Andric     if (!llvm::is_contained(HostOnlyArchives, SDLName)) {
2612bdd1243dSDimitry Andric       SDLNames.insert(std::string("-l") + SDLName);
2613349cc55cSDimitry Andric     }
2614349cc55cSDimitry Andric   }
2615349cc55cSDimitry Andric 
2616bdd1243dSDimitry Andric   for (auto Input : DriverArgs.getAllArgValues(options::OPT_INPUT)) {
2617bdd1243dSDimitry Andric     auto FileName = StringRef(Input);
2618bdd1243dSDimitry Andric     // Clang treats any unknown file types as archives and passes them to the
2619bdd1243dSDimitry Andric     // linker. Files with extension 'lib' are classified as TY_Object by clang
2620bdd1243dSDimitry Andric     // but they are usually archives. It is OK if the file is not really an
2621bdd1243dSDimitry Andric     // archive since GetSDLFromOffloadArchive will check the magic of the file
2622bdd1243dSDimitry Andric     // and only unbundle it if it is really an archive.
2623bdd1243dSDimitry Andric     const StringRef LibFileExt = ".lib";
2624bdd1243dSDimitry Andric     if (!llvm::sys::path::has_extension(FileName) ||
2625bdd1243dSDimitry Andric         types::lookupTypeForExtension(
2626bdd1243dSDimitry Andric             llvm::sys::path::extension(FileName).drop_front()) ==
2627bdd1243dSDimitry Andric             types::TY_INVALID ||
2628bdd1243dSDimitry Andric         llvm::sys::path::extension(FileName) == LibFileExt)
2629bdd1243dSDimitry Andric       SDLNames.insert(Input);
2630bdd1243dSDimitry Andric   }
2631bdd1243dSDimitry Andric 
2632349cc55cSDimitry Andric   // The search stops as soon as an SDL file is found. The driver then provides
2633bdd1243dSDimitry Andric   // the full filename of the SDL to the llvm-link command. If no SDL is found
2634bdd1243dSDimitry Andric   // after searching each LINKPATH with SEARCH-ORDER, it is possible that an
2635bdd1243dSDimitry Andric   // archive file lib<libname>.a exists and may contain bundled object files.
2636349cc55cSDimitry Andric   for (auto SDLName : SDLNames) {
2637349cc55cSDimitry Andric     // This is the only call to SDLSearch
2638349cc55cSDimitry Andric     if (!SDLSearch(D, DriverArgs, CC1Args, LibraryPaths, SDLName, Arch, Target,
26395f757f3fSDimitry Andric                    isBitCodeSDL)) {
2640349cc55cSDimitry Andric       GetSDLFromOffloadArchive(*C, D, *T, *JA, *Inputs, DriverArgs, CC1Args,
2641349cc55cSDimitry Andric                                LibraryPaths, SDLName, Arch, Target,
26425f757f3fSDimitry Andric                                isBitCodeSDL);
2643349cc55cSDimitry Andric     }
2644349cc55cSDimitry Andric   }
2645349cc55cSDimitry Andric }
2646349cc55cSDimitry Andric 
2647fe6060f1SDimitry Andric static llvm::opt::Arg *
getAMDGPUCodeObjectArgument(const Driver & D,const llvm::opt::ArgList & Args)2648fe6060f1SDimitry Andric getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
264906c3fb27SDimitry Andric   return Args.getLastArg(options::OPT_mcode_object_version_EQ);
2650fe6060f1SDimitry Andric }
2651fe6060f1SDimitry Andric 
checkAMDGPUCodeObjectVersion(const Driver & D,const llvm::opt::ArgList & Args)2652fe6060f1SDimitry Andric void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
2653fe6060f1SDimitry Andric                                          const llvm::opt::ArgList &Args) {
26545f757f3fSDimitry Andric   const unsigned MinCodeObjVer = 4;
265581ad6265SDimitry Andric   const unsigned MaxCodeObjVer = 5;
2656e8d8bef9SDimitry Andric 
2657fe6060f1SDimitry Andric   if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
2658fe6060f1SDimitry Andric     if (CodeObjArg->getOption().getID() ==
2659fe6060f1SDimitry Andric         options::OPT_mcode_object_version_EQ) {
2660fe6060f1SDimitry Andric       unsigned CodeObjVer = MaxCodeObjVer;
2661fe6060f1SDimitry Andric       auto Remnant =
2662fe6060f1SDimitry Andric           StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
2663fe6060f1SDimitry Andric       if (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer)
2664fe6060f1SDimitry Andric         D.Diag(diag::err_drv_invalid_int_value)
2665fe6060f1SDimitry Andric             << CodeObjArg->getAsString(Args) << CodeObjArg->getValue();
2666fe6060f1SDimitry Andric     }
2667fe6060f1SDimitry Andric   }
2668e8d8bef9SDimitry Andric }
2669e8d8bef9SDimitry Andric 
getAMDGPUCodeObjectVersion(const Driver & D,const llvm::opt::ArgList & Args)2670fe6060f1SDimitry Andric unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D,
2671fe6060f1SDimitry Andric                                            const llvm::opt::ArgList &Args) {
2672fe6060f1SDimitry Andric   unsigned CodeObjVer = 4; // default
267306c3fb27SDimitry Andric   if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args))
2674e8d8bef9SDimitry Andric     StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
2675e8d8bef9SDimitry Andric   return CodeObjVer;
2676e8d8bef9SDimitry Andric }
2677e8d8bef9SDimitry Andric 
haveAMDGPUCodeObjectVersionArgument(const Driver & D,const llvm::opt::ArgList & Args)2678fe6060f1SDimitry Andric bool tools::haveAMDGPUCodeObjectVersionArgument(
2679fe6060f1SDimitry Andric     const Driver &D, const llvm::opt::ArgList &Args) {
2680fe6060f1SDimitry Andric   return getAMDGPUCodeObjectArgument(D, Args) != nullptr;
2681fe6060f1SDimitry Andric }
2682fe6060f1SDimitry Andric 
addMachineOutlinerArgs(const Driver & D,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs,const llvm::Triple & Triple,bool IsLTO,const StringRef PluginOptPrefix)2683e8d8bef9SDimitry Andric void tools::addMachineOutlinerArgs(const Driver &D,
2684e8d8bef9SDimitry Andric                                    const llvm::opt::ArgList &Args,
2685e8d8bef9SDimitry Andric                                    llvm::opt::ArgStringList &CmdArgs,
2686bdd1243dSDimitry Andric                                    const llvm::Triple &Triple, bool IsLTO,
2687bdd1243dSDimitry Andric                                    const StringRef PluginOptPrefix) {
2688e8d8bef9SDimitry Andric   auto addArg = [&, IsLTO](const Twine &Arg) {
2689e8d8bef9SDimitry Andric     if (IsLTO) {
2690bdd1243dSDimitry Andric       assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
2691bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
2692e8d8bef9SDimitry Andric     } else {
2693e8d8bef9SDimitry Andric       CmdArgs.push_back("-mllvm");
2694e8d8bef9SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Arg));
2695e8d8bef9SDimitry Andric     }
2696e8d8bef9SDimitry Andric   };
2697e8d8bef9SDimitry Andric 
2698e8d8bef9SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_moutline,
2699e8d8bef9SDimitry Andric                                options::OPT_mno_outline)) {
2700e8d8bef9SDimitry Andric     if (A->getOption().matches(options::OPT_moutline)) {
2701e8d8bef9SDimitry Andric       // We only support -moutline in AArch64 and ARM targets right now. If
2702e8d8bef9SDimitry Andric       // we're not compiling for these, emit a warning and ignore the flag.
2703e8d8bef9SDimitry Andric       // Otherwise, add the proper mllvm flags.
27045f757f3fSDimitry Andric       if (!(Triple.isARM() || Triple.isThumb() || Triple.isAArch64())) {
2705e8d8bef9SDimitry Andric         D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
2706e8d8bef9SDimitry Andric       } else {
2707e8d8bef9SDimitry Andric         addArg(Twine("-enable-machine-outliner"));
2708e8d8bef9SDimitry Andric       }
2709e8d8bef9SDimitry Andric     } else {
2710e8d8bef9SDimitry Andric       // Disable all outlining behaviour.
2711e8d8bef9SDimitry Andric       addArg(Twine("-enable-machine-outliner=never"));
2712e8d8bef9SDimitry Andric     }
2713e8d8bef9SDimitry Andric   }
2714e8d8bef9SDimitry Andric }
2715fe6060f1SDimitry Andric 
addOpenMPDeviceRTL(const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef BitcodeSuffix,const llvm::Triple & Triple)2716fe6060f1SDimitry Andric void tools::addOpenMPDeviceRTL(const Driver &D,
2717fe6060f1SDimitry Andric                                const llvm::opt::ArgList &DriverArgs,
2718fe6060f1SDimitry Andric                                llvm::opt::ArgStringList &CC1Args,
2719fe6060f1SDimitry Andric                                StringRef BitcodeSuffix,
2720fe6060f1SDimitry Andric                                const llvm::Triple &Triple) {
2721fe6060f1SDimitry Andric   SmallVector<StringRef, 8> LibraryPaths;
2722349cc55cSDimitry Andric 
2723349cc55cSDimitry Andric   // Add path to clang lib / lib64 folder.
2724349cc55cSDimitry Andric   SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
2725bdd1243dSDimitry Andric   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
2726349cc55cSDimitry Andric   LibraryPaths.emplace_back(DefaultLibPath.c_str());
2727349cc55cSDimitry Andric 
2728fe6060f1SDimitry Andric   // Add user defined library paths from LIBRARY_PATH.
2729bdd1243dSDimitry Andric   std::optional<std::string> LibPath =
2730fe6060f1SDimitry Andric       llvm::sys::Process::GetEnv("LIBRARY_PATH");
2731fe6060f1SDimitry Andric   if (LibPath) {
2732fe6060f1SDimitry Andric     SmallVector<StringRef, 8> Frags;
2733fe6060f1SDimitry Andric     const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
2734fe6060f1SDimitry Andric     llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
2735fe6060f1SDimitry Andric     for (StringRef Path : Frags)
2736fe6060f1SDimitry Andric       LibraryPaths.emplace_back(Path.trim());
2737fe6060f1SDimitry Andric   }
2738fe6060f1SDimitry Andric 
2739fe6060f1SDimitry Andric   OptSpecifier LibomptargetBCPathOpt =
274081ad6265SDimitry Andric       Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
2741fe6060f1SDimitry Andric                         : options::OPT_libomptarget_nvptx_bc_path_EQ;
2742fe6060f1SDimitry Andric 
274381ad6265SDimitry Andric   StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx";
274481ad6265SDimitry Andric   std::string LibOmpTargetName =
274581ad6265SDimitry Andric       ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str();
2746349cc55cSDimitry Andric 
2747fe6060f1SDimitry Andric   // First check whether user specifies bc library
2748fe6060f1SDimitry Andric   if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
2749349cc55cSDimitry Andric     SmallString<128> LibOmpTargetFile(A->getValue());
2750349cc55cSDimitry Andric     if (llvm::sys::fs::exists(LibOmpTargetFile) &&
2751349cc55cSDimitry Andric         llvm::sys::fs::is_directory(LibOmpTargetFile)) {
2752349cc55cSDimitry Andric       llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
2753349cc55cSDimitry Andric     }
2754349cc55cSDimitry Andric 
2755349cc55cSDimitry Andric     if (llvm::sys::fs::exists(LibOmpTargetFile)) {
2756fe6060f1SDimitry Andric       CC1Args.push_back("-mlink-builtin-bitcode");
2757349cc55cSDimitry Andric       CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
2758fe6060f1SDimitry Andric     } else {
2759fe6060f1SDimitry Andric       D.Diag(diag::err_drv_omp_offload_target_bcruntime_not_found)
2760349cc55cSDimitry Andric           << LibOmpTargetFile;
2761fe6060f1SDimitry Andric     }
2762fe6060f1SDimitry Andric   } else {
2763fe6060f1SDimitry Andric     bool FoundBCLibrary = false;
2764fe6060f1SDimitry Andric 
2765fe6060f1SDimitry Andric     for (StringRef LibraryPath : LibraryPaths) {
2766fe6060f1SDimitry Andric       SmallString<128> LibOmpTargetFile(LibraryPath);
2767fe6060f1SDimitry Andric       llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
2768fe6060f1SDimitry Andric       if (llvm::sys::fs::exists(LibOmpTargetFile)) {
2769fe6060f1SDimitry Andric         CC1Args.push_back("-mlink-builtin-bitcode");
2770fe6060f1SDimitry Andric         CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
2771fe6060f1SDimitry Andric         FoundBCLibrary = true;
2772fe6060f1SDimitry Andric         break;
2773fe6060f1SDimitry Andric       }
2774fe6060f1SDimitry Andric     }
2775fe6060f1SDimitry Andric 
2776fe6060f1SDimitry Andric     if (!FoundBCLibrary)
2777fe6060f1SDimitry Andric       D.Diag(diag::err_drv_omp_offload_target_missingbcruntime)
2778fe6060f1SDimitry Andric           << LibOmpTargetName << ArchPrefix;
2779fe6060f1SDimitry Andric   }
2780fe6060f1SDimitry Andric }
addHIPRuntimeLibArgs(const ToolChain & TC,Compilation & C,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)27815f757f3fSDimitry Andric void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
278281ad6265SDimitry Andric                                  const llvm::opt::ArgList &Args,
278381ad6265SDimitry Andric                                  llvm::opt::ArgStringList &CmdArgs) {
27845f757f3fSDimitry Andric   if ((C.getActiveOffloadKinds() & Action::OFK_HIP) &&
278581ad6265SDimitry Andric       !Args.hasArg(options::OPT_nostdlib) &&
278681ad6265SDimitry Andric       !Args.hasArg(options::OPT_no_hip_rt)) {
278781ad6265SDimitry Andric     TC.AddHIPRuntimeLibArgs(Args, CmdArgs);
278881ad6265SDimitry Andric   } else {
278981ad6265SDimitry Andric     // Claim "no HIP libraries" arguments if any
2790bdd1243dSDimitry Andric     for (auto *Arg : Args.filtered(options::OPT_no_hip_rt)) {
279181ad6265SDimitry Andric       Arg->claim();
279281ad6265SDimitry Andric     }
279381ad6265SDimitry Andric   }
279481ad6265SDimitry Andric }
2795