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