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