xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/CommonArgs.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- CommonArgs.cpp - Args handling for multiple toolchains -*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "CommonArgs.h"
10e5dd7070Spatrick #include "Arch/AArch64.h"
11e5dd7070Spatrick #include "Arch/ARM.h"
12*12c85518Srobert #include "Arch/CSKY.h"
13*12c85518Srobert #include "Arch/LoongArch.h"
14a9ac8606Spatrick #include "Arch/M68k.h"
15e5dd7070Spatrick #include "Arch/Mips.h"
16e5dd7070Spatrick #include "Arch/PPC.h"
17*12c85518Srobert #include "Arch/RISCV.h"
18*12c85518Srobert #include "Arch/Sparc.h"
19e5dd7070Spatrick #include "Arch/SystemZ.h"
20ec727ea7Spatrick #include "Arch/VE.h"
21e5dd7070Spatrick #include "Arch/X86.h"
22*12c85518Srobert #include "HIPAMD.h"
23e5dd7070Spatrick #include "Hexagon.h"
24*12c85518Srobert #include "MSP430.h"
25e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
26e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
27e5dd7070Spatrick #include "clang/Basic/ObjCRuntime.h"
28e5dd7070Spatrick #include "clang/Basic/Version.h"
29e5dd7070Spatrick #include "clang/Config/config.h"
30e5dd7070Spatrick #include "clang/Driver/Action.h"
31e5dd7070Spatrick #include "clang/Driver/Compilation.h"
32e5dd7070Spatrick #include "clang/Driver/Driver.h"
33e5dd7070Spatrick #include "clang/Driver/DriverDiagnostic.h"
34a9ac8606Spatrick #include "clang/Driver/InputInfo.h"
35e5dd7070Spatrick #include "clang/Driver/Job.h"
36e5dd7070Spatrick #include "clang/Driver/Options.h"
37e5dd7070Spatrick #include "clang/Driver/SanitizerArgs.h"
38e5dd7070Spatrick #include "clang/Driver/ToolChain.h"
39e5dd7070Spatrick #include "clang/Driver/Util.h"
40e5dd7070Spatrick #include "clang/Driver/XRayArgs.h"
41e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
42*12c85518Srobert #include "llvm/ADT/SmallSet.h"
43e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
44e5dd7070Spatrick #include "llvm/ADT/StringExtras.h"
45e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
46e5dd7070Spatrick #include "llvm/ADT/Twine.h"
47*12c85518Srobert #include "llvm/BinaryFormat/Magic.h"
48a9ac8606Spatrick #include "llvm/Config/llvm-config.h"
49e5dd7070Spatrick #include "llvm/Option/Arg.h"
50e5dd7070Spatrick #include "llvm/Option/ArgList.h"
51e5dd7070Spatrick #include "llvm/Option/Option.h"
52e5dd7070Spatrick #include "llvm/Support/CodeGen.h"
53e5dd7070Spatrick #include "llvm/Support/Compression.h"
54e5dd7070Spatrick #include "llvm/Support/Debug.h"
55e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
56e5dd7070Spatrick #include "llvm/Support/FileSystem.h"
57e5dd7070Spatrick #include "llvm/Support/Host.h"
58e5dd7070Spatrick #include "llvm/Support/Path.h"
59e5dd7070Spatrick #include "llvm/Support/Process.h"
60e5dd7070Spatrick #include "llvm/Support/Program.h"
61e5dd7070Spatrick #include "llvm/Support/ScopedPrinter.h"
62e5dd7070Spatrick #include "llvm/Support/TargetParser.h"
63ec727ea7Spatrick #include "llvm/Support/Threading.h"
64e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h"
65e5dd7070Spatrick #include "llvm/Support/YAMLParser.h"
66*12c85518Srobert #include <optional>
67e5dd7070Spatrick 
68e5dd7070Spatrick using namespace clang::driver;
69e5dd7070Spatrick using namespace clang::driver::tools;
70e5dd7070Spatrick using namespace clang;
71e5dd7070Spatrick using namespace llvm::opt;
72e5dd7070Spatrick 
renderRpassOptions(const ArgList & Args,ArgStringList & CmdArgs,const StringRef PluginOptPrefix)73*12c85518Srobert static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs,
74*12c85518Srobert                                const StringRef PluginOptPrefix) {
75a9ac8606Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
76*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
77*12c85518Srobert                                          "-pass-remarks=" + A->getValue()));
78a9ac8606Spatrick 
79a9ac8606Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
80a9ac8606Spatrick     CmdArgs.push_back(Args.MakeArgString(
81*12c85518Srobert         Twine(PluginOptPrefix) + "-pass-remarks-missed=" + A->getValue()));
82a9ac8606Spatrick 
83a9ac8606Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
84a9ac8606Spatrick     CmdArgs.push_back(Args.MakeArgString(
85*12c85518Srobert         Twine(PluginOptPrefix) + "-pass-remarks-analysis=" + A->getValue()));
86a9ac8606Spatrick }
87a9ac8606Spatrick 
renderRemarksOptions(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple,const InputInfo & Input,const InputInfo & Output,const StringRef PluginOptPrefix)88a9ac8606Spatrick static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
89a9ac8606Spatrick                                  const llvm::Triple &Triple,
90a9ac8606Spatrick                                  const InputInfo &Input,
91*12c85518Srobert                                  const InputInfo &Output,
92*12c85518Srobert                                  const StringRef PluginOptPrefix) {
93a9ac8606Spatrick   StringRef Format = "yaml";
94a9ac8606Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
95a9ac8606Spatrick     Format = A->getValue();
96a9ac8606Spatrick 
97a9ac8606Spatrick   SmallString<128> F;
98a9ac8606Spatrick   const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
99a9ac8606Spatrick   if (A)
100a9ac8606Spatrick     F = A->getValue();
101a9ac8606Spatrick   else if (Output.isFilename())
102a9ac8606Spatrick     F = Output.getFilename();
103a9ac8606Spatrick 
104a9ac8606Spatrick   assert(!F.empty() && "Cannot determine remarks output name.");
105a9ac8606Spatrick   // Append "opt.ld.<format>" to the end of the file name.
106*12c85518Srobert   CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
107*12c85518Srobert                                        "opt-remarks-filename=" + F +
108*12c85518Srobert                                        ".opt.ld." + Format));
109a9ac8606Spatrick 
110a9ac8606Spatrick   if (const Arg *A =
111a9ac8606Spatrick           Args.getLastArg(options::OPT_foptimization_record_passes_EQ))
112a9ac8606Spatrick     CmdArgs.push_back(Args.MakeArgString(
113*12c85518Srobert         Twine(PluginOptPrefix) + "opt-remarks-passes=" + A->getValue()));
114a9ac8606Spatrick 
115*12c85518Srobert   CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
116*12c85518Srobert                                        "opt-remarks-format=" + Format.data()));
117a9ac8606Spatrick }
118a9ac8606Spatrick 
renderRemarksHotnessOptions(const ArgList & Args,ArgStringList & CmdArgs,const StringRef PluginOptPrefix)119a9ac8606Spatrick static void renderRemarksHotnessOptions(const ArgList &Args,
120*12c85518Srobert                                         ArgStringList &CmdArgs,
121*12c85518Srobert                                         const StringRef PluginOptPrefix) {
122a9ac8606Spatrick   if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
123a9ac8606Spatrick                    options::OPT_fno_diagnostics_show_hotness, false))
124*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
125*12c85518Srobert                                          "opt-remarks-with-hotness"));
126a9ac8606Spatrick 
127a9ac8606Spatrick   if (const Arg *A =
128a9ac8606Spatrick           Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ))
129*12c85518Srobert     CmdArgs.push_back(
130*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) +
131*12c85518Srobert                            "opt-remarks-hotness-threshold=" + A->getValue()));
132a9ac8606Spatrick }
133a9ac8606Spatrick 
addPathIfExists(const Driver & D,const Twine & Path,ToolChain::path_list & Paths)134e5dd7070Spatrick void tools::addPathIfExists(const Driver &D, const Twine &Path,
135e5dd7070Spatrick                             ToolChain::path_list &Paths) {
136e5dd7070Spatrick   if (D.getVFS().exists(Path))
137e5dd7070Spatrick     Paths.push_back(Path.str());
138e5dd7070Spatrick }
139e5dd7070Spatrick 
handleTargetFeaturesGroup(const ArgList & Args,std::vector<StringRef> & Features,OptSpecifier Group)140e5dd7070Spatrick void tools::handleTargetFeaturesGroup(const ArgList &Args,
141e5dd7070Spatrick                                       std::vector<StringRef> &Features,
142e5dd7070Spatrick                                       OptSpecifier Group) {
143e5dd7070Spatrick   for (const Arg *A : Args.filtered(Group)) {
144e5dd7070Spatrick     StringRef Name = A->getOption().getName();
145e5dd7070Spatrick     A->claim();
146e5dd7070Spatrick 
147e5dd7070Spatrick     // Skip over "-m".
148e5dd7070Spatrick     assert(Name.startswith("m") && "Invalid feature name.");
149e5dd7070Spatrick     Name = Name.substr(1);
150e5dd7070Spatrick 
151e5dd7070Spatrick     bool IsNegative = Name.startswith("no-");
152e5dd7070Spatrick     if (IsNegative)
153e5dd7070Spatrick       Name = Name.substr(3);
154e5dd7070Spatrick     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
155e5dd7070Spatrick   }
156e5dd7070Spatrick }
157e5dd7070Spatrick 
158*12c85518Srobert SmallVector<StringRef>
unifyTargetFeatures(ArrayRef<StringRef> Features)159*12c85518Srobert tools::unifyTargetFeatures(ArrayRef<StringRef> Features) {
160*12c85518Srobert   // Only add a feature if it hasn't been seen before starting from the end.
161*12c85518Srobert   SmallVector<StringRef> UnifiedFeatures;
162*12c85518Srobert   llvm::DenseSet<StringRef> UsedFeatures;
163*12c85518Srobert   for (StringRef Feature : llvm::reverse(Features)) {
164*12c85518Srobert     if (UsedFeatures.insert(Feature.drop_front()).second)
165*12c85518Srobert       UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature);
166ec727ea7Spatrick   }
167ec727ea7Spatrick 
168ec727ea7Spatrick   return UnifiedFeatures;
169ec727ea7Spatrick }
170ec727ea7Spatrick 
addDirectoryList(const ArgList & Args,ArgStringList & CmdArgs,const char * ArgName,const char * EnvVar)171e5dd7070Spatrick void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
172e5dd7070Spatrick                              const char *ArgName, const char *EnvVar) {
173e5dd7070Spatrick   const char *DirList = ::getenv(EnvVar);
174e5dd7070Spatrick   bool CombinedArg = false;
175e5dd7070Spatrick 
176e5dd7070Spatrick   if (!DirList)
177e5dd7070Spatrick     return; // Nothing to do.
178e5dd7070Spatrick 
179e5dd7070Spatrick   StringRef Name(ArgName);
180ec727ea7Spatrick   if (Name.equals("-I") || Name.equals("-L") || Name.empty())
181e5dd7070Spatrick     CombinedArg = true;
182e5dd7070Spatrick 
183e5dd7070Spatrick   StringRef Dirs(DirList);
184e5dd7070Spatrick   if (Dirs.empty()) // Empty string should not add '.'.
185e5dd7070Spatrick     return;
186e5dd7070Spatrick 
187e5dd7070Spatrick   StringRef::size_type Delim;
188e5dd7070Spatrick   while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
189e5dd7070Spatrick     if (Delim == 0) { // Leading colon.
190e5dd7070Spatrick       if (CombinedArg) {
191e5dd7070Spatrick         CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
192e5dd7070Spatrick       } else {
193e5dd7070Spatrick         CmdArgs.push_back(ArgName);
194e5dd7070Spatrick         CmdArgs.push_back(".");
195e5dd7070Spatrick       }
196e5dd7070Spatrick     } else {
197e5dd7070Spatrick       if (CombinedArg) {
198e5dd7070Spatrick         CmdArgs.push_back(
199e5dd7070Spatrick             Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
200e5dd7070Spatrick       } else {
201e5dd7070Spatrick         CmdArgs.push_back(ArgName);
202e5dd7070Spatrick         CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
203e5dd7070Spatrick       }
204e5dd7070Spatrick     }
205e5dd7070Spatrick     Dirs = Dirs.substr(Delim + 1);
206e5dd7070Spatrick   }
207e5dd7070Spatrick 
208e5dd7070Spatrick   if (Dirs.empty()) { // Trailing colon.
209e5dd7070Spatrick     if (CombinedArg) {
210e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
211e5dd7070Spatrick     } else {
212e5dd7070Spatrick       CmdArgs.push_back(ArgName);
213e5dd7070Spatrick       CmdArgs.push_back(".");
214e5dd7070Spatrick     }
215e5dd7070Spatrick   } else { // Add the last path.
216e5dd7070Spatrick     if (CombinedArg) {
217e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
218e5dd7070Spatrick     } else {
219e5dd7070Spatrick       CmdArgs.push_back(ArgName);
220e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(Dirs));
221e5dd7070Spatrick     }
222e5dd7070Spatrick   }
223e5dd7070Spatrick }
224e5dd7070Spatrick 
AddLinkerInputs(const ToolChain & TC,const InputInfoList & Inputs,const ArgList & Args,ArgStringList & CmdArgs,const JobAction & JA)225e5dd7070Spatrick void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
226e5dd7070Spatrick                             const ArgList &Args, ArgStringList &CmdArgs,
227e5dd7070Spatrick                             const JobAction &JA) {
228e5dd7070Spatrick   const Driver &D = TC.getDriver();
229e5dd7070Spatrick 
230e5dd7070Spatrick   // Add extra linker input arguments which are not treated as inputs
231e5dd7070Spatrick   // (constructed via -Xarch_).
232e5dd7070Spatrick   Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
233e5dd7070Spatrick 
234e5dd7070Spatrick   // LIBRARY_PATH are included before user inputs and only supported on native
235e5dd7070Spatrick   // toolchains.
236e5dd7070Spatrick   if (!TC.isCrossCompiling())
237e5dd7070Spatrick     addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
238e5dd7070Spatrick 
239e5dd7070Spatrick   for (const auto &II : Inputs) {
240ec727ea7Spatrick     // If the current tool chain refers to an OpenMP offloading host, we
241ec727ea7Spatrick     // should ignore inputs that refer to OpenMP offloading devices -
242e5dd7070Spatrick     // they will be embedded according to a proper linker script.
243e5dd7070Spatrick     if (auto *IA = II.getAction())
244e5dd7070Spatrick       if ((JA.isHostOffloading(Action::OFK_OpenMP) &&
245ec727ea7Spatrick            IA->isDeviceOffloading(Action::OFK_OpenMP)))
246e5dd7070Spatrick         continue;
247e5dd7070Spatrick 
248e5dd7070Spatrick     if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
249e5dd7070Spatrick       // Don't try to pass LLVM inputs unless we have native support.
250e5dd7070Spatrick       D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
251e5dd7070Spatrick 
252e5dd7070Spatrick     // Add filenames immediately.
253e5dd7070Spatrick     if (II.isFilename()) {
254e5dd7070Spatrick       CmdArgs.push_back(II.getFilename());
255e5dd7070Spatrick       continue;
256e5dd7070Spatrick     }
257e5dd7070Spatrick 
258*12c85518Srobert     // In some error cases, the input could be Nothing; skip those.
259*12c85518Srobert     if (II.isNothing())
260*12c85518Srobert       continue;
261*12c85518Srobert 
262e5dd7070Spatrick     // Otherwise, this is a linker input argument.
263e5dd7070Spatrick     const Arg &A = II.getInputArg();
264e5dd7070Spatrick 
265e5dd7070Spatrick     // Handle reserved library options.
266e5dd7070Spatrick     if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
267e5dd7070Spatrick       TC.AddCXXStdlibLibArgs(Args, CmdArgs);
268e5dd7070Spatrick     else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
269e5dd7070Spatrick       TC.AddCCKextLibArgs(Args, CmdArgs);
270e5dd7070Spatrick     else if (A.getOption().matches(options::OPT_z)) {
271e5dd7070Spatrick       // Pass -z prefix for gcc linker compatibility.
272e5dd7070Spatrick       A.claim();
273e5dd7070Spatrick       A.render(Args, CmdArgs);
274*12c85518Srobert     } else if (A.getOption().matches(options::OPT_b)) {
275*12c85518Srobert       const llvm::Triple &T = TC.getTriple();
276*12c85518Srobert       if (!T.isOSAIX()) {
277*12c85518Srobert         TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
278*12c85518Srobert             << A.getSpelling() << T.str();
279*12c85518Srobert       }
280*12c85518Srobert       // Pass -b prefix for AIX linker.
281*12c85518Srobert       A.claim();
282*12c85518Srobert       A.render(Args, CmdArgs);
283e5dd7070Spatrick     } else {
284e5dd7070Spatrick       A.renderAsInput(Args, CmdArgs);
285e5dd7070Spatrick     }
286e5dd7070Spatrick   }
287e5dd7070Spatrick }
288e5dd7070Spatrick 
addLinkerCompressDebugSectionsOption(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)289a9ac8606Spatrick void tools::addLinkerCompressDebugSectionsOption(
290a9ac8606Spatrick     const ToolChain &TC, const llvm::opt::ArgList &Args,
291a9ac8606Spatrick     llvm::opt::ArgStringList &CmdArgs) {
292a9ac8606Spatrick   // GNU ld supports --compress-debug-sections=none|zlib|zlib-gnu|zlib-gabi
293*12c85518Srobert   // whereas zlib is an alias to zlib-gabi and zlib-gnu is obsoleted. Therefore
294*12c85518Srobert   // -gz=none|zlib are translated to --compress-debug-sections=none|zlib. -gz
295*12c85518Srobert   // is not translated since ld --compress-debug-sections option requires an
296a9ac8606Spatrick   // argument.
297a9ac8606Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_gz_EQ)) {
298a9ac8606Spatrick     StringRef V = A->getValue();
299*12c85518Srobert     if (V == "none" || V == "zlib" || V == "zstd")
300a9ac8606Spatrick       CmdArgs.push_back(Args.MakeArgString("--compress-debug-sections=" + V));
301a9ac8606Spatrick     else
302a9ac8606Spatrick       TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
303*12c85518Srobert           << A->getSpelling() << V;
304a9ac8606Spatrick   }
305a9ac8606Spatrick }
306a9ac8606Spatrick 
AddTargetFeature(const ArgList & Args,std::vector<StringRef> & Features,OptSpecifier OnOpt,OptSpecifier OffOpt,StringRef FeatureName)307e5dd7070Spatrick void tools::AddTargetFeature(const ArgList &Args,
308e5dd7070Spatrick                              std::vector<StringRef> &Features,
309e5dd7070Spatrick                              OptSpecifier OnOpt, OptSpecifier OffOpt,
310e5dd7070Spatrick                              StringRef FeatureName) {
311e5dd7070Spatrick   if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
312e5dd7070Spatrick     if (A->getOption().matches(OnOpt))
313e5dd7070Spatrick       Features.push_back(Args.MakeArgString("+" + FeatureName));
314e5dd7070Spatrick     else
315e5dd7070Spatrick       Features.push_back(Args.MakeArgString("-" + FeatureName));
316e5dd7070Spatrick   }
317e5dd7070Spatrick }
318e5dd7070Spatrick 
319a9ac8606Spatrick /// Get the (LLVM) name of the AMDGPU gpu we are targeting.
getAMDGPUTargetGPU(const llvm::Triple & T,const ArgList & Args)320a9ac8606Spatrick static std::string getAMDGPUTargetGPU(const llvm::Triple &T,
321a9ac8606Spatrick                                       const ArgList &Args) {
322e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
323a9ac8606Spatrick     auto GPUName = getProcessorFromTargetID(T, A->getValue());
324a9ac8606Spatrick     return llvm::StringSwitch<std::string>(GPUName)
325e5dd7070Spatrick         .Cases("rv630", "rv635", "r600")
326e5dd7070Spatrick         .Cases("rv610", "rv620", "rs780", "rs880")
327e5dd7070Spatrick         .Case("rv740", "rv770")
328e5dd7070Spatrick         .Case("palm", "cedar")
329e5dd7070Spatrick         .Cases("sumo", "sumo2", "sumo")
330e5dd7070Spatrick         .Case("hemlock", "cypress")
331e5dd7070Spatrick         .Case("aruba", "cayman")
332a9ac8606Spatrick         .Default(GPUName.str());
333e5dd7070Spatrick   }
334e5dd7070Spatrick   return "";
335e5dd7070Spatrick }
336e5dd7070Spatrick 
getLanaiTargetCPU(const ArgList & Args)337e5dd7070Spatrick static std::string getLanaiTargetCPU(const ArgList &Args) {
338e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
339e5dd7070Spatrick     return A->getValue();
340e5dd7070Spatrick   }
341e5dd7070Spatrick   return "";
342e5dd7070Spatrick }
343e5dd7070Spatrick 
344e5dd7070Spatrick /// Get the (LLVM) name of the WebAssembly cpu we are targeting.
getWebAssemblyTargetCPU(const ArgList & Args)345e5dd7070Spatrick static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
346e5dd7070Spatrick   // If we have -mcpu=, use that.
347e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
348e5dd7070Spatrick     StringRef CPU = A->getValue();
349e5dd7070Spatrick 
350e5dd7070Spatrick #ifdef __wasm__
351e5dd7070Spatrick     // Handle "native" by examining the host. "native" isn't meaningful when
352e5dd7070Spatrick     // cross compiling, so only support this when the host is also WebAssembly.
353e5dd7070Spatrick     if (CPU == "native")
354e5dd7070Spatrick       return llvm::sys::getHostCPUName();
355e5dd7070Spatrick #endif
356e5dd7070Spatrick 
357e5dd7070Spatrick     return CPU;
358e5dd7070Spatrick   }
359e5dd7070Spatrick 
360e5dd7070Spatrick   return "generic";
361e5dd7070Spatrick }
362e5dd7070Spatrick 
getCPUName(const Driver & D,const ArgList & Args,const llvm::Triple & T,bool FromAs)363*12c85518Srobert std::string tools::getCPUName(const Driver &D, const ArgList &Args,
364*12c85518Srobert                               const llvm::Triple &T, bool FromAs) {
365e5dd7070Spatrick   Arg *A;
366e5dd7070Spatrick 
367e5dd7070Spatrick   switch (T.getArch()) {
368e5dd7070Spatrick   default:
369e5dd7070Spatrick     return "";
370e5dd7070Spatrick 
371e5dd7070Spatrick   case llvm::Triple::aarch64:
372e5dd7070Spatrick   case llvm::Triple::aarch64_32:
373e5dd7070Spatrick   case llvm::Triple::aarch64_be:
374e5dd7070Spatrick     return aarch64::getAArch64TargetCPU(Args, T, A);
375e5dd7070Spatrick 
376e5dd7070Spatrick   case llvm::Triple::arm:
377e5dd7070Spatrick   case llvm::Triple::armeb:
378e5dd7070Spatrick   case llvm::Triple::thumb:
379e5dd7070Spatrick   case llvm::Triple::thumbeb: {
380e5dd7070Spatrick     StringRef MArch, MCPU;
381e5dd7070Spatrick     arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
382e5dd7070Spatrick     return arm::getARMTargetCPU(MCPU, MArch, T);
383e5dd7070Spatrick   }
384e5dd7070Spatrick 
385e5dd7070Spatrick   case llvm::Triple::avr:
386e5dd7070Spatrick     if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ))
387e5dd7070Spatrick       return A->getValue();
388e5dd7070Spatrick     return "";
389e5dd7070Spatrick 
390a9ac8606Spatrick   case llvm::Triple::m68k:
391a9ac8606Spatrick     return m68k::getM68kTargetCPU(Args);
392a9ac8606Spatrick 
393e5dd7070Spatrick   case llvm::Triple::mips:
394e5dd7070Spatrick   case llvm::Triple::mipsel:
395e5dd7070Spatrick   case llvm::Triple::mips64:
396e5dd7070Spatrick   case llvm::Triple::mips64el: {
397e5dd7070Spatrick     StringRef CPUName;
398e5dd7070Spatrick     StringRef ABIName;
399e5dd7070Spatrick     mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
400ec727ea7Spatrick     return std::string(CPUName);
401e5dd7070Spatrick   }
402e5dd7070Spatrick 
403e5dd7070Spatrick   case llvm::Triple::nvptx:
404e5dd7070Spatrick   case llvm::Triple::nvptx64:
405e5dd7070Spatrick     if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
406e5dd7070Spatrick       return A->getValue();
407e5dd7070Spatrick     return "";
408e5dd7070Spatrick 
409e5dd7070Spatrick   case llvm::Triple::ppc:
410a9ac8606Spatrick   case llvm::Triple::ppcle:
411e5dd7070Spatrick   case llvm::Triple::ppc64:
412*12c85518Srobert   case llvm::Triple::ppc64le:
413*12c85518Srobert     return ppc::getPPCTargetCPU(Args, T);
414ec727ea7Spatrick 
415*12c85518Srobert   case llvm::Triple::csky:
416ec727ea7Spatrick     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
417ec727ea7Spatrick       return A->getValue();
418*12c85518Srobert     else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
419*12c85518Srobert       return A->getValue();
420*12c85518Srobert     else
421*12c85518Srobert       return "ck810";
422*12c85518Srobert   case llvm::Triple::riscv32:
423*12c85518Srobert   case llvm::Triple::riscv64:
424*12c85518Srobert     return riscv::getRISCVTargetCPU(Args, T);
425e5dd7070Spatrick 
426e5dd7070Spatrick   case llvm::Triple::bpfel:
427e5dd7070Spatrick   case llvm::Triple::bpfeb:
428*12c85518Srobert     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
429*12c85518Srobert       return A->getValue();
430*12c85518Srobert     return "";
431*12c85518Srobert 
432e5dd7070Spatrick   case llvm::Triple::sparc:
433e5dd7070Spatrick   case llvm::Triple::sparcel:
434e5dd7070Spatrick   case llvm::Triple::sparcv9:
435*12c85518Srobert     return sparc::getSparcTargetCPU(D, Args, T);
436e5dd7070Spatrick 
437e5dd7070Spatrick   case llvm::Triple::x86:
438e5dd7070Spatrick   case llvm::Triple::x86_64:
439*12c85518Srobert     return x86::getX86TargetCPU(D, Args, T);
440e5dd7070Spatrick 
441e5dd7070Spatrick   case llvm::Triple::hexagon:
442e5dd7070Spatrick     return "hexagon" +
443e5dd7070Spatrick            toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
444e5dd7070Spatrick 
445e5dd7070Spatrick   case llvm::Triple::lanai:
446e5dd7070Spatrick     return getLanaiTargetCPU(Args);
447e5dd7070Spatrick 
448e5dd7070Spatrick   case llvm::Triple::systemz:
449e5dd7070Spatrick     return systemz::getSystemZTargetCPU(Args);
450e5dd7070Spatrick 
451e5dd7070Spatrick   case llvm::Triple::r600:
452e5dd7070Spatrick   case llvm::Triple::amdgcn:
453a9ac8606Spatrick     return getAMDGPUTargetGPU(T, Args);
454e5dd7070Spatrick 
455e5dd7070Spatrick   case llvm::Triple::wasm32:
456e5dd7070Spatrick   case llvm::Triple::wasm64:
457ec727ea7Spatrick     return std::string(getWebAssemblyTargetCPU(Args));
458e5dd7070Spatrick   }
459e5dd7070Spatrick }
460e5dd7070Spatrick 
getWebAssemblyTargetFeatures(const ArgList & Args,std::vector<StringRef> & Features)461*12c85518Srobert static void getWebAssemblyTargetFeatures(const ArgList &Args,
462*12c85518Srobert                                          std::vector<StringRef> &Features) {
463*12c85518Srobert   handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
464*12c85518Srobert }
465*12c85518Srobert 
getTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,bool ForAS,bool IsAux)466*12c85518Srobert void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
467*12c85518Srobert                               const ArgList &Args, ArgStringList &CmdArgs,
468*12c85518Srobert                               bool ForAS, bool IsAux) {
469*12c85518Srobert   std::vector<StringRef> Features;
470*12c85518Srobert   switch (Triple.getArch()) {
471*12c85518Srobert   default:
472*12c85518Srobert     break;
473*12c85518Srobert   case llvm::Triple::mips:
474*12c85518Srobert   case llvm::Triple::mipsel:
475*12c85518Srobert   case llvm::Triple::mips64:
476*12c85518Srobert   case llvm::Triple::mips64el:
477*12c85518Srobert     mips::getMIPSTargetFeatures(D, Triple, Args, Features);
478*12c85518Srobert     break;
479*12c85518Srobert   case llvm::Triple::arm:
480*12c85518Srobert   case llvm::Triple::armeb:
481*12c85518Srobert   case llvm::Triple::thumb:
482*12c85518Srobert   case llvm::Triple::thumbeb:
483*12c85518Srobert     arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS);
484*12c85518Srobert     break;
485*12c85518Srobert   case llvm::Triple::ppc:
486*12c85518Srobert   case llvm::Triple::ppcle:
487*12c85518Srobert   case llvm::Triple::ppc64:
488*12c85518Srobert   case llvm::Triple::ppc64le:
489*12c85518Srobert     ppc::getPPCTargetFeatures(D, Triple, Args, Features);
490*12c85518Srobert     break;
491*12c85518Srobert   case llvm::Triple::riscv32:
492*12c85518Srobert   case llvm::Triple::riscv64:
493*12c85518Srobert     riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
494*12c85518Srobert     break;
495*12c85518Srobert   case llvm::Triple::systemz:
496*12c85518Srobert     systemz::getSystemZTargetFeatures(D, Args, Features);
497*12c85518Srobert     break;
498*12c85518Srobert   case llvm::Triple::aarch64:
499*12c85518Srobert   case llvm::Triple::aarch64_32:
500*12c85518Srobert   case llvm::Triple::aarch64_be:
501*12c85518Srobert     aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
502*12c85518Srobert     break;
503*12c85518Srobert   case llvm::Triple::x86:
504*12c85518Srobert   case llvm::Triple::x86_64:
505*12c85518Srobert     x86::getX86TargetFeatures(D, Triple, Args, Features);
506*12c85518Srobert     break;
507*12c85518Srobert   case llvm::Triple::hexagon:
508*12c85518Srobert     hexagon::getHexagonTargetFeatures(D, Args, Features);
509*12c85518Srobert     break;
510*12c85518Srobert   case llvm::Triple::wasm32:
511*12c85518Srobert   case llvm::Triple::wasm64:
512*12c85518Srobert     getWebAssemblyTargetFeatures(Args, Features);
513*12c85518Srobert     break;
514*12c85518Srobert   case llvm::Triple::sparc:
515*12c85518Srobert   case llvm::Triple::sparcel:
516*12c85518Srobert   case llvm::Triple::sparcv9:
517*12c85518Srobert     sparc::getSparcTargetFeatures(D, Args, Features);
518*12c85518Srobert     break;
519*12c85518Srobert   case llvm::Triple::r600:
520*12c85518Srobert   case llvm::Triple::amdgcn:
521*12c85518Srobert     amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
522*12c85518Srobert     break;
523*12c85518Srobert   case llvm::Triple::nvptx:
524*12c85518Srobert   case llvm::Triple::nvptx64:
525*12c85518Srobert     NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features);
526*12c85518Srobert     break;
527*12c85518Srobert   case llvm::Triple::m68k:
528*12c85518Srobert     m68k::getM68kTargetFeatures(D, Triple, Args, Features);
529*12c85518Srobert     break;
530*12c85518Srobert   case llvm::Triple::msp430:
531*12c85518Srobert     msp430::getMSP430TargetFeatures(D, Args, Features);
532*12c85518Srobert     break;
533*12c85518Srobert   case llvm::Triple::ve:
534*12c85518Srobert     ve::getVETargetFeatures(D, Args, Features);
535*12c85518Srobert     break;
536*12c85518Srobert   case llvm::Triple::csky:
537*12c85518Srobert     csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features);
538*12c85518Srobert     break;
539*12c85518Srobert   case llvm::Triple::loongarch32:
540*12c85518Srobert   case llvm::Triple::loongarch64:
541*12c85518Srobert     loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features);
542*12c85518Srobert     break;
543*12c85518Srobert   }
544*12c85518Srobert 
545*12c85518Srobert   for (auto Feature : unifyTargetFeatures(Features)) {
546*12c85518Srobert     CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
547*12c85518Srobert     CmdArgs.push_back(Feature.data());
548*12c85518Srobert   }
549*12c85518Srobert }
550*12c85518Srobert 
getLTOParallelism(const ArgList & Args,const Driver & D)551ec727ea7Spatrick llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
552e5dd7070Spatrick   Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
553ec727ea7Spatrick   if (!LtoJobsArg)
554ec727ea7Spatrick     return {};
555ec727ea7Spatrick   if (!llvm::get_threadpool_strategy(LtoJobsArg->getValue()))
556ec727ea7Spatrick     D.Diag(diag::err_drv_invalid_int_value)
557ec727ea7Spatrick         << LtoJobsArg->getAsString(Args) << LtoJobsArg->getValue();
558ec727ea7Spatrick   return LtoJobsArg->getValue();
559e5dd7070Spatrick }
560e5dd7070Spatrick 
561*12c85518Srobert // CloudABI and PS4/PS5 use -ffunction-sections and -fdata-sections by default.
isUseSeparateSections(const llvm::Triple & Triple)562e5dd7070Spatrick bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
563*12c85518Srobert   return Triple.getOS() == llvm::Triple::CloudABI || Triple.isPS();
564e5dd7070Spatrick }
565e5dd7070Spatrick 
addLTOOptions(const ToolChain & ToolChain,const ArgList & Args,ArgStringList & CmdArgs,const InputInfo & Output,const InputInfo & Input,bool IsThinLTO)566ec727ea7Spatrick void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
567e5dd7070Spatrick                           ArgStringList &CmdArgs, const InputInfo &Output,
568e5dd7070Spatrick                           const InputInfo &Input, bool IsThinLTO) {
569*12c85518Srobert   const bool IsOSAIX = ToolChain.getTriple().isOSAIX();
570ec727ea7Spatrick   const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
571ec727ea7Spatrick   const Driver &D = ToolChain.getDriver();
572ec727ea7Spatrick   if (llvm::sys::path::filename(Linker) != "ld.lld" &&
573ec727ea7Spatrick       llvm::sys::path::stem(Linker) != "ld.lld") {
574ec727ea7Spatrick     // Tell the linker to load the plugin. This has to come before
575*12c85518Srobert     // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to
576*12c85518Srobert     // come before any -plugin-opt/-bplugin_opt that -Wl might forward.
577*12c85518Srobert     const char *PluginPrefix = IsOSAIX ? "-bplugin:" : "";
578*12c85518Srobert     const char *PluginName = IsOSAIX ? "/libLTO" : "/LLVMgold";
579*12c85518Srobert 
580*12c85518Srobert     if (!IsOSAIX)
581e5dd7070Spatrick       CmdArgs.push_back("-plugin");
582e5dd7070Spatrick 
583e5dd7070Spatrick #if defined(_WIN32)
584e5dd7070Spatrick     const char *Suffix = ".dll";
585e5dd7070Spatrick #elif defined(__APPLE__)
586e5dd7070Spatrick     const char *Suffix = ".dylib";
587e5dd7070Spatrick #else
588e5dd7070Spatrick     const char *Suffix = ".so";
589e5dd7070Spatrick #endif
590e5dd7070Spatrick 
591e5dd7070Spatrick     SmallString<1024> Plugin;
592*12c85518Srobert     llvm::sys::path::native(Twine(D.Dir) +
593*12c85518Srobert                                 "/../" CLANG_INSTALL_LIBDIR_BASENAME +
594*12c85518Srobert                                 PluginName + Suffix,
595e5dd7070Spatrick                             Plugin);
596*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin));
597*12c85518Srobert   }
598*12c85518Srobert 
599*12c85518Srobert   const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt=";
600*12c85518Srobert   const char *ExtraDash = IsOSAIX ? "-" : "";
601*12c85518Srobert 
602*12c85518Srobert   // Note, this solution is far from perfect, better to encode it into IR
603*12c85518Srobert   // metadata, but this may not be worth it, since it looks like aranges is on
604*12c85518Srobert   // the way out.
605*12c85518Srobert   if (Args.hasArg(options::OPT_gdwarf_aranges)) {
606*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
607*12c85518Srobert                                          "-generate-arange-section"));
608ec727ea7Spatrick   }
609e5dd7070Spatrick 
610e5dd7070Spatrick   // Try to pass driver level flags relevant to LTO code generation down to
611e5dd7070Spatrick   // the plugin.
612e5dd7070Spatrick 
613e5dd7070Spatrick   // Handle flags for selecting CPU variants.
614*12c85518Srobert   std::string CPU = getCPUName(D, Args, ToolChain.getTriple());
615e5dd7070Spatrick   if (!CPU.empty())
616*12c85518Srobert     CmdArgs.push_back(
617*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU));
618e5dd7070Spatrick 
619e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
620ec727ea7Spatrick     // The optimization level matches
621ec727ea7Spatrick     // CompilerInvocation.cpp:getOptimizationLevel().
622e5dd7070Spatrick     StringRef OOpt;
623e5dd7070Spatrick     if (A->getOption().matches(options::OPT_O4) ||
624e5dd7070Spatrick         A->getOption().matches(options::OPT_Ofast))
625e5dd7070Spatrick       OOpt = "3";
626ec727ea7Spatrick     else if (A->getOption().matches(options::OPT_O)) {
627e5dd7070Spatrick       OOpt = A->getValue();
628ec727ea7Spatrick       if (OOpt == "g")
629ec727ea7Spatrick         OOpt = "1";
630ec727ea7Spatrick       else if (OOpt == "s" || OOpt == "z")
631ec727ea7Spatrick         OOpt = "2";
632ec727ea7Spatrick     } else if (A->getOption().matches(options::OPT_O0))
633e5dd7070Spatrick       OOpt = "0";
634e5dd7070Spatrick     if (!OOpt.empty())
635*12c85518Srobert       CmdArgs.push_back(
636*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "O" + OOpt));
637e5dd7070Spatrick   }
638e5dd7070Spatrick 
639*12c85518Srobert   if (Args.hasArg(options::OPT_gsplit_dwarf))
640*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(
641*12c85518Srobert         Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo"));
642e5dd7070Spatrick 
643e5dd7070Spatrick   if (IsThinLTO)
644*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto"));
645e5dd7070Spatrick 
646ec727ea7Spatrick   StringRef Parallelism = getLTOParallelism(Args, D);
647ec727ea7Spatrick   if (!Parallelism.empty())
648e5dd7070Spatrick     CmdArgs.push_back(
649*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "jobs=" + Parallelism));
650e5dd7070Spatrick 
651e5dd7070Spatrick   // If an explicit debugger tuning argument appeared, pass it along.
652*12c85518Srobert   if (Arg *A =
653*12c85518Srobert           Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
654e5dd7070Spatrick     if (A->getOption().matches(options::OPT_glldb))
655*12c85518Srobert       CmdArgs.push_back(
656*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=lldb"));
657e5dd7070Spatrick     else if (A->getOption().matches(options::OPT_gsce))
658*12c85518Srobert       CmdArgs.push_back(
659*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=sce"));
660a9ac8606Spatrick     else if (A->getOption().matches(options::OPT_gdbx))
661*12c85518Srobert       CmdArgs.push_back(
662*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=dbx"));
663e5dd7070Spatrick     else
664*12c85518Srobert       CmdArgs.push_back(
665*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=gdb"));
666*12c85518Srobert   }
667*12c85518Srobert 
668*12c85518Srobert   if (IsOSAIX) {
669*12c85518Srobert     // On AIX, clang assumes strict-dwarf is true if any debug option is
670*12c85518Srobert     // specified, unless it is told explicitly not to assume so.
671*12c85518Srobert     Arg *A = Args.getLastArg(options::OPT_g_Group);
672*12c85518Srobert     bool EnableDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
673*12c85518Srobert                            !A->getOption().matches(options::OPT_ggdb0);
674*12c85518Srobert     if (EnableDebugInfo && Args.hasFlag(options::OPT_gstrict_dwarf,
675*12c85518Srobert                                         options::OPT_gno_strict_dwarf, true))
676*12c85518Srobert       CmdArgs.push_back(
677*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-strict-dwarf=true"));
678*12c85518Srobert 
679*12c85518Srobert     if (Args.getLastArg(options::OPT_mabi_EQ_vec_extabi))
680*12c85518Srobert       CmdArgs.push_back(
681*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + "-vec-extabi"));
682e5dd7070Spatrick   }
683e5dd7070Spatrick 
684e5dd7070Spatrick   bool UseSeparateSections =
685e5dd7070Spatrick       isUseSeparateSections(ToolChain.getEffectiveTriple());
686e5dd7070Spatrick 
687e5dd7070Spatrick   if (Args.hasFlag(options::OPT_ffunction_sections,
688*12c85518Srobert                    options::OPT_fno_function_sections, UseSeparateSections))
689*12c85518Srobert     CmdArgs.push_back(
690*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=1"));
691*12c85518Srobert   else if (Args.hasArg(options::OPT_fno_function_sections))
692*12c85518Srobert     CmdArgs.push_back(
693*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=0"));
694e5dd7070Spatrick 
695e5dd7070Spatrick   if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
696*12c85518Srobert                    UseSeparateSections))
697*12c85518Srobert     CmdArgs.push_back(
698*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=1"));
699*12c85518Srobert   else if (Args.hasArg(options::OPT_fno_data_sections))
700*12c85518Srobert     CmdArgs.push_back(
701*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=0"));
702*12c85518Srobert 
703*12c85518Srobert   // Pass an option to enable split machine functions.
704*12c85518Srobert   if (auto *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
705*12c85518Srobert                                 options::OPT_fno_split_machine_functions)) {
706*12c85518Srobert     if (A->getOption().matches(options::OPT_fsplit_machine_functions))
707*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
708*12c85518Srobert                                            "-split-machine-functions"));
709e5dd7070Spatrick   }
710e5dd7070Spatrick 
711e5dd7070Spatrick   if (Arg *A = getLastProfileSampleUseArg(Args)) {
712e5dd7070Spatrick     StringRef FName = A->getValue();
713e5dd7070Spatrick     if (!llvm::sys::fs::exists(FName))
714ec727ea7Spatrick       D.Diag(diag::err_drv_no_such_file) << FName;
715e5dd7070Spatrick     else
716*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
717*12c85518Srobert                                            "sample-profile=" + FName));
718e5dd7070Spatrick   }
719e5dd7070Spatrick 
720e5dd7070Spatrick   auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate,
721e5dd7070Spatrick                                            options::OPT_fcs_profile_generate_EQ,
722e5dd7070Spatrick                                            options::OPT_fno_profile_generate);
723e5dd7070Spatrick   if (CSPGOGenerateArg &&
724e5dd7070Spatrick       CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
725e5dd7070Spatrick     CSPGOGenerateArg = nullptr;
726e5dd7070Spatrick 
727e5dd7070Spatrick   auto *ProfileUseArg = getLastProfileUseArg(Args);
728e5dd7070Spatrick 
729e5dd7070Spatrick   if (CSPGOGenerateArg) {
730*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
731*12c85518Srobert                                          "cs-profile-generate"));
732e5dd7070Spatrick     if (CSPGOGenerateArg->getOption().matches(
733e5dd7070Spatrick             options::OPT_fcs_profile_generate_EQ)) {
734e5dd7070Spatrick       SmallString<128> Path(CSPGOGenerateArg->getValue());
735e5dd7070Spatrick       llvm::sys::path::append(Path, "default_%m.profraw");
736*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
737*12c85518Srobert                                            "cs-profile-path=" + Path));
738e5dd7070Spatrick     } else
739e5dd7070Spatrick       CmdArgs.push_back(
740*12c85518Srobert           Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
741*12c85518Srobert                              "cs-profile-path=default_%m.profraw"));
742e5dd7070Spatrick   } else if (ProfileUseArg) {
743e5dd7070Spatrick     SmallString<128> Path(
744e5dd7070Spatrick         ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
745e5dd7070Spatrick     if (Path.empty() || llvm::sys::fs::is_directory(Path))
746e5dd7070Spatrick       llvm::sys::path::append(Path, "default.profdata");
747*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
748*12c85518Srobert                                          "cs-profile-path=" + Path));
749e5dd7070Spatrick   }
750e5dd7070Spatrick 
751*12c85518Srobert   // This controls whether or not we perform JustMyCode instrumentation.
752*12c85518Srobert   if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) {
753*12c85518Srobert     if (ToolChain.getEffectiveTriple().isOSBinFormatELF())
754*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
755*12c85518Srobert                                            "-enable-jmc-instrument"));
756a9ac8606Spatrick     else
757*12c85518Srobert       D.Diag(clang::diag::warn_drv_fjmc_for_elf_only);
758e5dd7070Spatrick   }
759e5dd7070Spatrick 
760*12c85518Srobert   if (Arg *A = Args.getLastArg(options::OPT_femulated_tls,
761*12c85518Srobert                                options::OPT_fno_emulated_tls)) {
762*12c85518Srobert     bool Enable = A->getOption().getID() == options::OPT_femulated_tls;
763*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(
764*12c85518Srobert         Twine(PluginOptPrefix) + "-emulated-tls=" + (Enable ? "1" : "0")));
765*12c85518Srobert   }
766*12c85518Srobert 
767*12c85518Srobert   if (Args.hasFlag(options::OPT_fstack_size_section,
768*12c85518Srobert                    options::OPT_fno_stack_size_section, false))
769*12c85518Srobert     CmdArgs.push_back(
770*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "-stack-size-section"));
771a9ac8606Spatrick 
772e5dd7070Spatrick   // Setup statistics file output.
773ec727ea7Spatrick   SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
774e5dd7070Spatrick   if (!StatsFile.empty())
775e5dd7070Spatrick     CmdArgs.push_back(
776*12c85518Srobert         Args.MakeArgString(Twine(PluginOptPrefix) + "stats-file=" + StatsFile));
777ec727ea7Spatrick 
778*12c85518Srobert   // Setup crash diagnostics dir.
779*12c85518Srobert   if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
780*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(
781*12c85518Srobert         Twine(PluginOptPrefix) + "-crash-diagnostics-dir=" + A->getValue()));
782*12c85518Srobert 
783*12c85518Srobert   addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true, PluginOptPrefix);
784a9ac8606Spatrick 
785a9ac8606Spatrick   // Handle remark diagnostics on screen options: '-Rpass-*'.
786*12c85518Srobert   renderRpassOptions(Args, CmdArgs, PluginOptPrefix);
787a9ac8606Spatrick 
788a9ac8606Spatrick   // Handle serialized remarks options: '-fsave-optimization-record'
789a9ac8606Spatrick   // and '-foptimization-record-*'.
790a9ac8606Spatrick   if (willEmitRemarks(Args))
791a9ac8606Spatrick     renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input,
792*12c85518Srobert                          Output, PluginOptPrefix);
793a9ac8606Spatrick 
794a9ac8606Spatrick   // Handle remarks hotness/threshold related options.
795*12c85518Srobert   renderRemarksHotnessOptions(Args, CmdArgs, PluginOptPrefix);
796a9ac8606Spatrick 
797a9ac8606Spatrick   addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(),
798*12c85518Srobert                          /*IsLTO=*/true, PluginOptPrefix);
799*12c85518Srobert }
800*12c85518Srobert 
addOpenMPRuntimeSpecificRPath(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)801*12c85518Srobert void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
802*12c85518Srobert                                           const ArgList &Args,
803*12c85518Srobert                                           ArgStringList &CmdArgs) {
804*12c85518Srobert 
805*12c85518Srobert   if (Args.hasFlag(options::OPT_fopenmp_implicit_rpath,
806*12c85518Srobert                    options::OPT_fno_openmp_implicit_rpath, true)) {
807*12c85518Srobert     // Default to clang lib / lib64 folder, i.e. the same location as device
808*12c85518Srobert     // runtime
809*12c85518Srobert     SmallString<256> DefaultLibPath =
810*12c85518Srobert         llvm::sys::path::parent_path(TC.getDriver().Dir);
811*12c85518Srobert     llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
812*12c85518Srobert     CmdArgs.push_back("-rpath");
813*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(DefaultLibPath));
814*12c85518Srobert   }
815*12c85518Srobert }
816*12c85518Srobert 
addOpenMPRuntimeLibraryPath(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)817*12c85518Srobert void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
818*12c85518Srobert                                         const ArgList &Args,
819*12c85518Srobert                                         ArgStringList &CmdArgs) {
820*12c85518Srobert   // Default to clang lib / lib64 folder, i.e. the same location as device
821*12c85518Srobert   // runtime.
822*12c85518Srobert   SmallString<256> DefaultLibPath =
823*12c85518Srobert       llvm::sys::path::parent_path(TC.getDriver().Dir);
824*12c85518Srobert   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
825*12c85518Srobert   CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
826e5dd7070Spatrick }
827e5dd7070Spatrick 
addArchSpecificRPath(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)828e5dd7070Spatrick void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
829e5dd7070Spatrick                                  ArgStringList &CmdArgs) {
830ec727ea7Spatrick   // Enable -frtlib-add-rpath by default for the case of VE.
831ec727ea7Spatrick   const bool IsVE = TC.getTriple().isVE();
832ec727ea7Spatrick   bool DefaultValue = IsVE;
833e5dd7070Spatrick   if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
834ec727ea7Spatrick                     options::OPT_fno_rtlib_add_rpath, DefaultValue))
835e5dd7070Spatrick     return;
836e5dd7070Spatrick 
837e5dd7070Spatrick   std::string CandidateRPath = TC.getArchSpecificLibPath();
838e5dd7070Spatrick   if (TC.getVFS().exists(CandidateRPath)) {
839e5dd7070Spatrick     CmdArgs.push_back("-rpath");
840*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(CandidateRPath));
841e5dd7070Spatrick   }
842e5dd7070Spatrick }
843e5dd7070Spatrick 
addOpenMPRuntime(ArgStringList & CmdArgs,const ToolChain & TC,const ArgList & Args,bool ForceStaticHostRuntime,bool IsOffloadingHost,bool GompNeedsRT)844e5dd7070Spatrick bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
845e5dd7070Spatrick                              const ArgList &Args, bool ForceStaticHostRuntime,
846e5dd7070Spatrick                              bool IsOffloadingHost, bool GompNeedsRT) {
847e5dd7070Spatrick   if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
848e5dd7070Spatrick                     options::OPT_fno_openmp, false))
849e5dd7070Spatrick     return false;
850e5dd7070Spatrick 
851e5dd7070Spatrick   Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args);
852e5dd7070Spatrick 
853e5dd7070Spatrick   if (RTKind == Driver::OMPRT_Unknown)
854e5dd7070Spatrick     // Already diagnosed.
855e5dd7070Spatrick     return false;
856e5dd7070Spatrick 
857e5dd7070Spatrick   if (ForceStaticHostRuntime)
858e5dd7070Spatrick     CmdArgs.push_back("-Bstatic");
859e5dd7070Spatrick 
860e5dd7070Spatrick   switch (RTKind) {
861e5dd7070Spatrick   case Driver::OMPRT_OMP:
862e5dd7070Spatrick     CmdArgs.push_back("-lomp");
863e5dd7070Spatrick     break;
864e5dd7070Spatrick   case Driver::OMPRT_GOMP:
865e5dd7070Spatrick     CmdArgs.push_back("-lgomp");
866e5dd7070Spatrick     break;
867e5dd7070Spatrick   case Driver::OMPRT_IOMP5:
868e5dd7070Spatrick     CmdArgs.push_back("-liomp5");
869e5dd7070Spatrick     break;
870e5dd7070Spatrick   case Driver::OMPRT_Unknown:
871e5dd7070Spatrick     break;
872e5dd7070Spatrick   }
873e5dd7070Spatrick 
874e5dd7070Spatrick   if (ForceStaticHostRuntime)
875e5dd7070Spatrick     CmdArgs.push_back("-Bdynamic");
876e5dd7070Spatrick 
877e5dd7070Spatrick   if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT)
878e5dd7070Spatrick       CmdArgs.push_back("-lrt");
879e5dd7070Spatrick 
880e5dd7070Spatrick   if (IsOffloadingHost)
881e5dd7070Spatrick     CmdArgs.push_back("-lomptarget");
882e5dd7070Spatrick 
883*12c85518Srobert   if (IsOffloadingHost && !Args.hasArg(options::OPT_nogpulib))
884*12c85518Srobert     CmdArgs.push_back("-lomptarget.devicertl");
885*12c85518Srobert 
886e5dd7070Spatrick   addArchSpecificRPath(TC, Args, CmdArgs);
887e5dd7070Spatrick 
888*12c85518Srobert   if (RTKind == Driver::OMPRT_OMP)
889*12c85518Srobert     addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
890*12c85518Srobert   addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
891*12c85518Srobert 
892e5dd7070Spatrick   return true;
893e5dd7070Spatrick }
894e5dd7070Spatrick 
addFortranRuntimeLibs(const ToolChain & TC,llvm::opt::ArgStringList & CmdArgs)895*12c85518Srobert void tools::addFortranRuntimeLibs(const ToolChain &TC,
896*12c85518Srobert                                   llvm::opt::ArgStringList &CmdArgs) {
897*12c85518Srobert   if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
898*12c85518Srobert     CmdArgs.push_back("Fortran_main.lib");
899*12c85518Srobert     CmdArgs.push_back("FortranRuntime.lib");
900*12c85518Srobert     CmdArgs.push_back("FortranDecimal.lib");
901*12c85518Srobert   } else {
902*12c85518Srobert     CmdArgs.push_back("-lFortran_main");
903*12c85518Srobert     CmdArgs.push_back("-lFortranRuntime");
904*12c85518Srobert     CmdArgs.push_back("-lFortranDecimal");
905*12c85518Srobert   }
906*12c85518Srobert }
907*12c85518Srobert 
addFortranRuntimeLibraryPath(const ToolChain & TC,const llvm::opt::ArgList & Args,ArgStringList & CmdArgs)908*12c85518Srobert void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
909*12c85518Srobert                                          const llvm::opt::ArgList &Args,
910*12c85518Srobert                                          ArgStringList &CmdArgs) {
911*12c85518Srobert   // NOTE: Generating executables by Flang is considered an "experimental"
912*12c85518Srobert   // feature and hence this is guarded with a command line option.
913*12c85518Srobert   // TODO: Make this work unconditionally once Flang is mature enough.
914*12c85518Srobert   if (!Args.hasArg(options::OPT_flang_experimental_exec))
915*12c85518Srobert     return;
916*12c85518Srobert 
917*12c85518Srobert   // Default to the <driver-path>/../lib directory. This works fine on the
918*12c85518Srobert   // platforms that we have tested so far. We will probably have to re-fine
919*12c85518Srobert   // this in the future. In particular, on some platforms, we may need to use
920*12c85518Srobert   // lib64 instead of lib.
921*12c85518Srobert   SmallString<256> DefaultLibPath =
922*12c85518Srobert       llvm::sys::path::parent_path(TC.getDriver().Dir);
923*12c85518Srobert   llvm::sys::path::append(DefaultLibPath, "lib");
924*12c85518Srobert   if (TC.getTriple().isKnownWindowsMSVCEnvironment())
925*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
926*12c85518Srobert   else
927*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
928*12c85518Srobert }
929*12c85518Srobert 
addSanitizerRuntime(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer,bool IsShared,bool IsWhole)930e5dd7070Spatrick static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
931e5dd7070Spatrick                                 ArgStringList &CmdArgs, StringRef Sanitizer,
932e5dd7070Spatrick                                 bool IsShared, bool IsWhole) {
933e5dd7070Spatrick   // Wrap any static runtimes that must be forced into executable in
934e5dd7070Spatrick   // whole-archive.
935e5dd7070Spatrick   if (IsWhole) CmdArgs.push_back("--whole-archive");
936e5dd7070Spatrick   CmdArgs.push_back(TC.getCompilerRTArgString(
937e5dd7070Spatrick       Args, Sanitizer, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static));
938e5dd7070Spatrick   if (IsWhole) CmdArgs.push_back("--no-whole-archive");
939e5dd7070Spatrick 
940e5dd7070Spatrick   if (IsShared) {
941e5dd7070Spatrick     addArchSpecificRPath(TC, Args, CmdArgs);
942e5dd7070Spatrick   }
943e5dd7070Spatrick }
944e5dd7070Spatrick 
945e5dd7070Spatrick // Tries to use a file with the list of dynamic symbols that need to be exported
946e5dd7070Spatrick // from the runtime library. Returns true if the file was found.
addSanitizerDynamicList(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer)947e5dd7070Spatrick static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
948e5dd7070Spatrick                                     ArgStringList &CmdArgs,
949e5dd7070Spatrick                                     StringRef Sanitizer) {
950e5dd7070Spatrick   // Solaris ld defaults to --export-dynamic behaviour but doesn't support
951e5dd7070Spatrick   // the option, so don't try to pass it.
952e5dd7070Spatrick   if (TC.getTriple().getOS() == llvm::Triple::Solaris)
953e5dd7070Spatrick     return true;
954e5dd7070Spatrick   SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
955e5dd7070Spatrick   if (llvm::sys::fs::exists(SanRT + ".syms")) {
956e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
957e5dd7070Spatrick     return true;
958e5dd7070Spatrick   }
959e5dd7070Spatrick   return false;
960e5dd7070Spatrick }
961e5dd7070Spatrick 
getAsNeededOption(const ToolChain & TC,bool as_needed)962*12c85518Srobert const char *tools::getAsNeededOption(const ToolChain &TC, bool as_needed) {
963a9ac8606Spatrick   assert(!TC.getTriple().isOSAIX() &&
964a9ac8606Spatrick          "AIX linker does not support any form of --as-needed option yet.");
965a9ac8606Spatrick 
966a9ac8606Spatrick   // While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases
967a9ac8606Spatrick   // for the native forms -z ignore/-z record, they are missing in Illumos,
968a9ac8606Spatrick   // so always use the native form.
969a9ac8606Spatrick   if (TC.getTriple().isOSSolaris())
970a9ac8606Spatrick     return as_needed ? "-zignore" : "-zrecord";
971a9ac8606Spatrick   else
972a9ac8606Spatrick     return as_needed ? "--as-needed" : "--no-as-needed";
973a9ac8606Spatrick }
974a9ac8606Spatrick 
linkSanitizerRuntimeDeps(const ToolChain & TC,ArgStringList & CmdArgs)975e5dd7070Spatrick void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
976e5dd7070Spatrick                                      ArgStringList &CmdArgs) {
977e5dd7070Spatrick   // Force linking against the system libraries sanitizers depends on
978e5dd7070Spatrick   // (see PR15823 why this is necessary).
979a9ac8606Spatrick   CmdArgs.push_back(getAsNeededOption(TC, false));
980e5dd7070Spatrick   // There's no libpthread or librt on RTEMS & Android.
981e5dd7070Spatrick   if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
982e5dd7070Spatrick       !TC.getTriple().isAndroid()) {
983e5dd7070Spatrick     CmdArgs.push_back("-lpthread");
984e5dd7070Spatrick     if (!TC.getTriple().isOSOpenBSD())
985e5dd7070Spatrick       CmdArgs.push_back("-lrt");
986e5dd7070Spatrick   }
987e5dd7070Spatrick   CmdArgs.push_back("-lm");
988e5dd7070Spatrick   // There's no libdl on all OSes.
989a9ac8606Spatrick   if (!TC.getTriple().isOSFreeBSD() && !TC.getTriple().isOSNetBSD() &&
990e5dd7070Spatrick       !TC.getTriple().isOSOpenBSD() &&
991e5dd7070Spatrick       TC.getTriple().getOS() != llvm::Triple::RTEMS)
992e5dd7070Spatrick     CmdArgs.push_back("-ldl");
993e5dd7070Spatrick   // Required for backtrace on some OSes
994e5dd7070Spatrick   if (TC.getTriple().isOSFreeBSD() ||
995a9ac8606Spatrick       TC.getTriple().isOSNetBSD() ||
996a9ac8606Spatrick       TC.getTriple().isOSOpenBSD())
997e5dd7070Spatrick     CmdArgs.push_back("-lexecinfo");
998*12c85518Srobert   // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl
999*12c85518Srobert   // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv
1000*12c85518Srobert   // requirement.
1001*12c85518Srobert   if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
1002*12c85518Srobert       !TC.getTriple().isMusl())
1003*12c85518Srobert     CmdArgs.push_back("-lresolv");
1004e5dd7070Spatrick }
1005e5dd7070Spatrick 
1006e5dd7070Spatrick static void
collectSanitizerRuntimes(const ToolChain & TC,const ArgList & Args,SmallVectorImpl<StringRef> & SharedRuntimes,SmallVectorImpl<StringRef> & StaticRuntimes,SmallVectorImpl<StringRef> & NonWholeStaticRuntimes,SmallVectorImpl<StringRef> & HelperStaticRuntimes,SmallVectorImpl<StringRef> & RequiredSymbols)1007e5dd7070Spatrick collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
1008e5dd7070Spatrick                          SmallVectorImpl<StringRef> &SharedRuntimes,
1009e5dd7070Spatrick                          SmallVectorImpl<StringRef> &StaticRuntimes,
1010e5dd7070Spatrick                          SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
1011e5dd7070Spatrick                          SmallVectorImpl<StringRef> &HelperStaticRuntimes,
1012e5dd7070Spatrick                          SmallVectorImpl<StringRef> &RequiredSymbols) {
1013*12c85518Srobert   const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
1014e5dd7070Spatrick   // Collect shared runtimes.
1015e5dd7070Spatrick   if (SanArgs.needsSharedRt()) {
1016e5dd7070Spatrick     if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
1017e5dd7070Spatrick       SharedRuntimes.push_back("asan");
1018e5dd7070Spatrick       if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
1019e5dd7070Spatrick         HelperStaticRuntimes.push_back("asan-preinit");
1020e5dd7070Spatrick     }
1021a9ac8606Spatrick     if (SanArgs.needsMemProfRt() && SanArgs.linkRuntimes()) {
1022a9ac8606Spatrick       SharedRuntimes.push_back("memprof");
1023a9ac8606Spatrick       if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
1024a9ac8606Spatrick         HelperStaticRuntimes.push_back("memprof-preinit");
1025a9ac8606Spatrick     }
1026e5dd7070Spatrick     if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
1027e5dd7070Spatrick       if (SanArgs.requiresMinimalRuntime())
1028e5dd7070Spatrick         SharedRuntimes.push_back("ubsan_minimal");
1029e5dd7070Spatrick       else
1030e5dd7070Spatrick         SharedRuntimes.push_back("ubsan_standalone");
1031e5dd7070Spatrick     }
1032e5dd7070Spatrick     if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
1033*12c85518Srobert       SharedRuntimes.push_back("scudo_standalone");
1034e5dd7070Spatrick     }
1035a9ac8606Spatrick     if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes())
1036a9ac8606Spatrick       SharedRuntimes.push_back("tsan");
1037a9ac8606Spatrick     if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
1038a9ac8606Spatrick       if (SanArgs.needsHwasanAliasesRt())
1039a9ac8606Spatrick         SharedRuntimes.push_back("hwasan_aliases");
1040a9ac8606Spatrick       else
1041e5dd7070Spatrick         SharedRuntimes.push_back("hwasan");
1042*12c85518Srobert       if (!Args.hasArg(options::OPT_shared))
1043*12c85518Srobert         HelperStaticRuntimes.push_back("hwasan-preinit");
1044e5dd7070Spatrick     }
1045a9ac8606Spatrick   }
1046e5dd7070Spatrick 
1047e5dd7070Spatrick   // The stats_client library is also statically linked into DSOs.
1048e5dd7070Spatrick   if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes())
1049e5dd7070Spatrick     StaticRuntimes.push_back("stats_client");
1050e5dd7070Spatrick 
1051*12c85518Srobert   // Always link the static runtime regardless of DSO or executable.
1052*12c85518Srobert   if (SanArgs.needsAsanRt())
1053*12c85518Srobert     HelperStaticRuntimes.push_back("asan_static");
1054*12c85518Srobert 
1055e5dd7070Spatrick   // Collect static runtimes.
1056ec727ea7Spatrick   if (Args.hasArg(options::OPT_shared)) {
1057ec727ea7Spatrick     // Don't link static runtimes into DSOs.
1058e5dd7070Spatrick     return;
1059e5dd7070Spatrick   }
1060ec727ea7Spatrick 
1061ec727ea7Spatrick   // Each static runtime that has a DSO counterpart above is excluded below,
1062ec727ea7Spatrick   // but runtimes that exist only as static are not affected by needsSharedRt.
1063ec727ea7Spatrick 
1064ec727ea7Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
1065e5dd7070Spatrick     StaticRuntimes.push_back("asan");
1066e5dd7070Spatrick     if (SanArgs.linkCXXRuntimes())
1067e5dd7070Spatrick       StaticRuntimes.push_back("asan_cxx");
1068e5dd7070Spatrick   }
1069e5dd7070Spatrick 
1070a9ac8606Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt() &&
1071a9ac8606Spatrick       SanArgs.linkRuntimes()) {
1072a9ac8606Spatrick     StaticRuntimes.push_back("memprof");
1073a9ac8606Spatrick     if (SanArgs.linkCXXRuntimes())
1074a9ac8606Spatrick       StaticRuntimes.push_back("memprof_cxx");
1075a9ac8606Spatrick   }
1076a9ac8606Spatrick 
1077ec727ea7Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
1078a9ac8606Spatrick     if (SanArgs.needsHwasanAliasesRt()) {
1079a9ac8606Spatrick       StaticRuntimes.push_back("hwasan_aliases");
1080a9ac8606Spatrick       if (SanArgs.linkCXXRuntimes())
1081a9ac8606Spatrick         StaticRuntimes.push_back("hwasan_aliases_cxx");
1082a9ac8606Spatrick     } else {
1083e5dd7070Spatrick       StaticRuntimes.push_back("hwasan");
1084e5dd7070Spatrick       if (SanArgs.linkCXXRuntimes())
1085e5dd7070Spatrick         StaticRuntimes.push_back("hwasan_cxx");
1086e5dd7070Spatrick     }
1087a9ac8606Spatrick   }
1088e5dd7070Spatrick   if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes())
1089e5dd7070Spatrick     StaticRuntimes.push_back("dfsan");
1090e5dd7070Spatrick   if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes())
1091e5dd7070Spatrick     StaticRuntimes.push_back("lsan");
1092e5dd7070Spatrick   if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) {
1093e5dd7070Spatrick     StaticRuntimes.push_back("msan");
1094e5dd7070Spatrick     if (SanArgs.linkCXXRuntimes())
1095e5dd7070Spatrick       StaticRuntimes.push_back("msan_cxx");
1096e5dd7070Spatrick   }
1097a9ac8606Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt() &&
1098a9ac8606Spatrick       SanArgs.linkRuntimes()) {
1099e5dd7070Spatrick     StaticRuntimes.push_back("tsan");
1100e5dd7070Spatrick     if (SanArgs.linkCXXRuntimes())
1101e5dd7070Spatrick       StaticRuntimes.push_back("tsan_cxx");
1102e5dd7070Spatrick   }
1103ec727ea7Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
1104e5dd7070Spatrick     if (SanArgs.requiresMinimalRuntime()) {
1105e5dd7070Spatrick       StaticRuntimes.push_back("ubsan_minimal");
1106e5dd7070Spatrick     } else {
1107e5dd7070Spatrick       StaticRuntimes.push_back("ubsan_standalone");
1108e5dd7070Spatrick       if (SanArgs.linkCXXRuntimes())
1109e5dd7070Spatrick         StaticRuntimes.push_back("ubsan_standalone_cxx");
1110e5dd7070Spatrick     }
1111e5dd7070Spatrick   }
1112e5dd7070Spatrick   if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) {
1113e5dd7070Spatrick     NonWholeStaticRuntimes.push_back("safestack");
1114e5dd7070Spatrick     RequiredSymbols.push_back("__safestack_init");
1115e5dd7070Spatrick   }
1116ec727ea7Spatrick   if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes())) {
1117e5dd7070Spatrick     if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes())
1118e5dd7070Spatrick       StaticRuntimes.push_back("cfi");
1119e5dd7070Spatrick     if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) {
1120e5dd7070Spatrick       StaticRuntimes.push_back("cfi_diag");
1121e5dd7070Spatrick       if (SanArgs.linkCXXRuntimes())
1122e5dd7070Spatrick         StaticRuntimes.push_back("ubsan_standalone_cxx");
1123e5dd7070Spatrick     }
1124ec727ea7Spatrick   }
1125e5dd7070Spatrick   if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) {
1126e5dd7070Spatrick     NonWholeStaticRuntimes.push_back("stats");
1127e5dd7070Spatrick     RequiredSymbols.push_back("__sanitizer_stats_register");
1128e5dd7070Spatrick   }
1129ec727ea7Spatrick   if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
1130*12c85518Srobert     StaticRuntimes.push_back("scudo_standalone");
1131e5dd7070Spatrick     if (SanArgs.linkCXXRuntimes())
1132*12c85518Srobert       StaticRuntimes.push_back("scudo_standalone_cxx");
1133e5dd7070Spatrick   }
1134e5dd7070Spatrick }
1135e5dd7070Spatrick 
1136e5dd7070Spatrick // Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
1137e5dd7070Spatrick // C runtime, etc). Returns true if sanitizer system deps need to be linked in.
addSanitizerRuntimes(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)1138e5dd7070Spatrick bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
1139e5dd7070Spatrick                                  ArgStringList &CmdArgs) {
1140e5dd7070Spatrick   SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
1141e5dd7070Spatrick       NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
1142e5dd7070Spatrick   collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
1143e5dd7070Spatrick                            NonWholeStaticRuntimes, HelperStaticRuntimes,
1144e5dd7070Spatrick                            RequiredSymbols);
1145e5dd7070Spatrick 
1146*12c85518Srobert   const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
1147e5dd7070Spatrick   // Inject libfuzzer dependencies.
1148e5dd7070Spatrick   if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
1149e5dd7070Spatrick       !Args.hasArg(options::OPT_shared)) {
1150e5dd7070Spatrick 
1151e5dd7070Spatrick     addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
1152a9ac8606Spatrick     if (SanArgs.needsFuzzerInterceptors())
1153a9ac8606Spatrick       addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer_interceptors", false,
1154a9ac8606Spatrick                           true);
1155a9ac8606Spatrick     if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) {
1156a9ac8606Spatrick       bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
1157a9ac8606Spatrick                                  !Args.hasArg(options::OPT_static);
1158a9ac8606Spatrick       if (OnlyLibstdcxxStatic)
1159a9ac8606Spatrick         CmdArgs.push_back("-Bstatic");
1160e5dd7070Spatrick       TC.AddCXXStdlibLibArgs(Args, CmdArgs);
1161a9ac8606Spatrick       if (OnlyLibstdcxxStatic)
1162a9ac8606Spatrick         CmdArgs.push_back("-Bdynamic");
1163a9ac8606Spatrick     }
1164e5dd7070Spatrick   }
1165e5dd7070Spatrick 
1166e5dd7070Spatrick   for (auto RT : SharedRuntimes)
1167e5dd7070Spatrick     addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false);
1168e5dd7070Spatrick   for (auto RT : HelperStaticRuntimes)
1169e5dd7070Spatrick     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
1170e5dd7070Spatrick   bool AddExportDynamic = false;
1171e5dd7070Spatrick   for (auto RT : StaticRuntimes) {
1172e5dd7070Spatrick     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
1173e5dd7070Spatrick     AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
1174e5dd7070Spatrick   }
1175e5dd7070Spatrick   for (auto RT : NonWholeStaticRuntimes) {
1176e5dd7070Spatrick     addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false);
1177e5dd7070Spatrick     AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
1178e5dd7070Spatrick   }
1179e5dd7070Spatrick   for (auto S : RequiredSymbols) {
1180e5dd7070Spatrick     CmdArgs.push_back("-u");
1181e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(S));
1182e5dd7070Spatrick   }
1183e5dd7070Spatrick   // If there is a static runtime with no dynamic list, force all the symbols
1184e5dd7070Spatrick   // to be dynamic to be sure we export sanitizer interface functions.
1185e5dd7070Spatrick   if (AddExportDynamic)
1186e5dd7070Spatrick     CmdArgs.push_back("--export-dynamic");
1187e5dd7070Spatrick 
1188e5dd7070Spatrick   if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
1189ec727ea7Spatrick     CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
1190e5dd7070Spatrick 
1191*12c85518Srobert   if (SanArgs.hasMemTag()) {
1192*12c85518Srobert     if (!TC.getTriple().isAndroid()) {
1193*12c85518Srobert       TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1194*12c85518Srobert           << "-fsanitize=memtag*" << TC.getTriple().str();
1195*12c85518Srobert     }
1196*12c85518Srobert     CmdArgs.push_back(
1197*12c85518Srobert         Args.MakeArgString("--android-memtag-mode=" + SanArgs.getMemtagMode()));
1198*12c85518Srobert     if (SanArgs.hasMemtagHeap())
1199*12c85518Srobert       CmdArgs.push_back("--android-memtag-heap");
1200*12c85518Srobert     if (SanArgs.hasMemtagStack())
1201*12c85518Srobert       CmdArgs.push_back("--android-memtag-stack");
1202*12c85518Srobert   }
1203*12c85518Srobert 
1204e5dd7070Spatrick   return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
1205e5dd7070Spatrick }
1206e5dd7070Spatrick 
addXRayRuntime(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)1207e5dd7070Spatrick bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) {
1208e5dd7070Spatrick   if (Args.hasArg(options::OPT_shared))
1209e5dd7070Spatrick     return false;
1210e5dd7070Spatrick 
1211e5dd7070Spatrick   if (TC.getXRayArgs().needsXRayRt()) {
1212e5dd7070Spatrick     CmdArgs.push_back("-whole-archive");
1213e5dd7070Spatrick     CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray"));
1214e5dd7070Spatrick     for (const auto &Mode : TC.getXRayArgs().modeList())
1215e5dd7070Spatrick       CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode));
1216e5dd7070Spatrick     CmdArgs.push_back("-no-whole-archive");
1217e5dd7070Spatrick     return true;
1218e5dd7070Spatrick   }
1219e5dd7070Spatrick 
1220e5dd7070Spatrick   return false;
1221e5dd7070Spatrick }
1222e5dd7070Spatrick 
linkXRayRuntimeDeps(const ToolChain & TC,ArgStringList & CmdArgs)1223e5dd7070Spatrick void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
1224a9ac8606Spatrick   CmdArgs.push_back(getAsNeededOption(TC, false));
1225e5dd7070Spatrick   CmdArgs.push_back("-lpthread");
1226e5dd7070Spatrick   if (!TC.getTriple().isOSOpenBSD())
1227e5dd7070Spatrick     CmdArgs.push_back("-lrt");
1228e5dd7070Spatrick   CmdArgs.push_back("-lm");
1229e5dd7070Spatrick 
1230e5dd7070Spatrick   if (!TC.getTriple().isOSFreeBSD() &&
1231e5dd7070Spatrick       !TC.getTriple().isOSNetBSD() &&
1232e5dd7070Spatrick       !TC.getTriple().isOSOpenBSD())
1233e5dd7070Spatrick     CmdArgs.push_back("-ldl");
1234e5dd7070Spatrick }
1235e5dd7070Spatrick 
areOptimizationsEnabled(const ArgList & Args)1236e5dd7070Spatrick bool tools::areOptimizationsEnabled(const ArgList &Args) {
1237e5dd7070Spatrick   // Find the last -O arg and see if it is non-zero.
1238e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_O_Group))
1239e5dd7070Spatrick     return !A->getOption().matches(options::OPT_O0);
1240e5dd7070Spatrick   // Defaults to -O0.
1241e5dd7070Spatrick   return false;
1242e5dd7070Spatrick }
1243e5dd7070Spatrick 
SplitDebugName(const JobAction & JA,const ArgList & Args,const InputInfo & Input,const InputInfo & Output)1244a9ac8606Spatrick const char *tools::SplitDebugName(const JobAction &JA, const ArgList &Args,
1245a9ac8606Spatrick                                   const InputInfo &Input,
1246e5dd7070Spatrick                                   const InputInfo &Output) {
1247a9ac8606Spatrick   auto AddPostfix = [JA](auto &F) {
1248a9ac8606Spatrick     if (JA.getOffloadingDeviceKind() == Action::OFK_HIP)
1249a9ac8606Spatrick       F += (Twine("_") + JA.getOffloadingArch()).str();
1250a9ac8606Spatrick     F += ".dwo";
1251a9ac8606Spatrick   };
1252e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
1253e5dd7070Spatrick     if (StringRef(A->getValue()) == "single")
1254e5dd7070Spatrick       return Args.MakeArgString(Output.getFilename());
1255e5dd7070Spatrick 
1256e5dd7070Spatrick   Arg *FinalOutput = Args.getLastArg(options::OPT_o);
1257e5dd7070Spatrick   if (FinalOutput && Args.hasArg(options::OPT_c)) {
1258e5dd7070Spatrick     SmallString<128> T(FinalOutput->getValue());
1259a9ac8606Spatrick     llvm::sys::path::remove_filename(T);
1260a9ac8606Spatrick     llvm::sys::path::append(T, llvm::sys::path::stem(FinalOutput->getValue()));
1261a9ac8606Spatrick     AddPostfix(T);
1262e5dd7070Spatrick     return Args.MakeArgString(T);
1263e5dd7070Spatrick   } else {
1264e5dd7070Spatrick     // Use the compilation dir.
1265a9ac8606Spatrick     Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
1266a9ac8606Spatrick                              options::OPT_fdebug_compilation_dir_EQ);
1267a9ac8606Spatrick     SmallString<128> T(A ? A->getValue() : "");
1268e5dd7070Spatrick     SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
1269a9ac8606Spatrick     AddPostfix(F);
1270e5dd7070Spatrick     T += F;
1271a9ac8606Spatrick     return Args.MakeArgString(T);
1272e5dd7070Spatrick   }
1273e5dd7070Spatrick }
1274e5dd7070Spatrick 
SplitDebugInfo(const ToolChain & TC,Compilation & C,const Tool & T,const JobAction & JA,const ArgList & Args,const InputInfo & Output,const char * OutFile)1275e5dd7070Spatrick void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
1276e5dd7070Spatrick                            const JobAction &JA, const ArgList &Args,
1277e5dd7070Spatrick                            const InputInfo &Output, const char *OutFile) {
1278e5dd7070Spatrick   ArgStringList ExtractArgs;
1279e5dd7070Spatrick   ExtractArgs.push_back("--extract-dwo");
1280e5dd7070Spatrick 
1281e5dd7070Spatrick   ArgStringList StripArgs;
1282e5dd7070Spatrick   StripArgs.push_back("--strip-dwo");
1283e5dd7070Spatrick 
1284e5dd7070Spatrick   // Grabbing the output of the earlier compile step.
1285e5dd7070Spatrick   StripArgs.push_back(Output.getFilename());
1286e5dd7070Spatrick   ExtractArgs.push_back(Output.getFilename());
1287e5dd7070Spatrick   ExtractArgs.push_back(OutFile);
1288e5dd7070Spatrick 
1289e5dd7070Spatrick   const char *Exec =
1290e5dd7070Spatrick       Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY));
1291e5dd7070Spatrick   InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
1292e5dd7070Spatrick 
1293e5dd7070Spatrick   // First extract the dwo sections.
1294a9ac8606Spatrick   C.addCommand(std::make_unique<Command>(JA, T,
1295a9ac8606Spatrick                                          ResponseFileSupport::AtFileCurCP(),
1296a9ac8606Spatrick                                          Exec, ExtractArgs, II, Output));
1297e5dd7070Spatrick 
1298e5dd7070Spatrick   // Then remove them from the original .o file.
1299ec727ea7Spatrick   C.addCommand(std::make_unique<Command>(
1300a9ac8606Spatrick       JA, T, ResponseFileSupport::AtFileCurCP(), Exec, StripArgs, II, Output));
1301e5dd7070Spatrick }
1302e5dd7070Spatrick 
1303e5dd7070Spatrick // Claim options we don't want to warn if they are unused. We do this for
1304e5dd7070Spatrick // options that build systems might add but are unused when assembling or only
1305e5dd7070Spatrick // running the preprocessor for example.
claimNoWarnArgs(const ArgList & Args)1306e5dd7070Spatrick void tools::claimNoWarnArgs(const ArgList &Args) {
1307e5dd7070Spatrick   // Don't warn about unused -f(no-)?lto.  This can happen when we're
1308e5dd7070Spatrick   // preprocessing, precompiling or assembling.
1309e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_flto_EQ);
1310e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_flto);
1311e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_fno_lto);
1312e5dd7070Spatrick }
1313e5dd7070Spatrick 
getLastProfileUseArg(const ArgList & Args)1314e5dd7070Spatrick Arg *tools::getLastProfileUseArg(const ArgList &Args) {
1315e5dd7070Spatrick   auto *ProfileUseArg = Args.getLastArg(
1316e5dd7070Spatrick       options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
1317e5dd7070Spatrick       options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
1318e5dd7070Spatrick       options::OPT_fno_profile_instr_use);
1319e5dd7070Spatrick 
1320e5dd7070Spatrick   if (ProfileUseArg &&
1321e5dd7070Spatrick       ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
1322e5dd7070Spatrick     ProfileUseArg = nullptr;
1323e5dd7070Spatrick 
1324e5dd7070Spatrick   return ProfileUseArg;
1325e5dd7070Spatrick }
1326e5dd7070Spatrick 
getLastProfileSampleUseArg(const ArgList & Args)1327e5dd7070Spatrick Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) {
1328e5dd7070Spatrick   auto *ProfileSampleUseArg = Args.getLastArg(
1329e5dd7070Spatrick       options::OPT_fprofile_sample_use, options::OPT_fprofile_sample_use_EQ,
1330e5dd7070Spatrick       options::OPT_fauto_profile, options::OPT_fauto_profile_EQ,
1331e5dd7070Spatrick       options::OPT_fno_profile_sample_use, options::OPT_fno_auto_profile);
1332e5dd7070Spatrick 
1333e5dd7070Spatrick   if (ProfileSampleUseArg &&
1334e5dd7070Spatrick       (ProfileSampleUseArg->getOption().matches(
1335e5dd7070Spatrick            options::OPT_fno_profile_sample_use) ||
1336e5dd7070Spatrick        ProfileSampleUseArg->getOption().matches(options::OPT_fno_auto_profile)))
1337e5dd7070Spatrick     return nullptr;
1338e5dd7070Spatrick 
1339e5dd7070Spatrick   return Args.getLastArg(options::OPT_fprofile_sample_use_EQ,
1340e5dd7070Spatrick                          options::OPT_fauto_profile_EQ);
1341e5dd7070Spatrick }
1342e5dd7070Spatrick 
RelocationModelName(llvm::Reloc::Model Model)1343*12c85518Srobert const char *tools::RelocationModelName(llvm::Reloc::Model Model) {
1344*12c85518Srobert   switch (Model) {
1345*12c85518Srobert   case llvm::Reloc::Static:
1346*12c85518Srobert     return "static";
1347*12c85518Srobert   case llvm::Reloc::PIC_:
1348*12c85518Srobert     return "pic";
1349*12c85518Srobert   case llvm::Reloc::DynamicNoPIC:
1350*12c85518Srobert     return "dynamic-no-pic";
1351*12c85518Srobert   case llvm::Reloc::ROPI:
1352*12c85518Srobert     return "ropi";
1353*12c85518Srobert   case llvm::Reloc::RWPI:
1354*12c85518Srobert     return "rwpi";
1355*12c85518Srobert   case llvm::Reloc::ROPI_RWPI:
1356*12c85518Srobert     return "ropi-rwpi";
1357*12c85518Srobert   }
1358*12c85518Srobert   llvm_unreachable("Unknown Reloc::Model kind");
1359*12c85518Srobert }
1360*12c85518Srobert 
1361e5dd7070Spatrick /// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments.  Then,
1362e5dd7070Spatrick /// smooshes them together with platform defaults, to decide whether
1363e5dd7070Spatrick /// this compile should be using PIC mode or not. Returns a tuple of
1364e5dd7070Spatrick /// (RelocationModel, PICLevel, IsPIE).
1365e5dd7070Spatrick std::tuple<llvm::Reloc::Model, unsigned, bool>
ParsePICArgs(const ToolChain & ToolChain,const ArgList & Args)1366e5dd7070Spatrick tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
1367e5dd7070Spatrick   const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple();
1368e5dd7070Spatrick   const llvm::Triple &Triple = ToolChain.getTriple();
1369e5dd7070Spatrick 
1370*12c85518Srobert   bool PIE = ToolChain.isPIEDefault(Args);
1371e5dd7070Spatrick   bool PIC = PIE || ToolChain.isPICDefault();
1372e5dd7070Spatrick   // The Darwin/MachO default to use PIC does not apply when using -static.
1373e5dd7070Spatrick   if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static))
1374e5dd7070Spatrick     PIE = PIC = false;
1375e5dd7070Spatrick   bool IsPICLevelTwo = PIC;
1376e5dd7070Spatrick 
1377e5dd7070Spatrick   bool KernelOrKext =
1378e5dd7070Spatrick       Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
1379e5dd7070Spatrick 
1380e5dd7070Spatrick   // Android-specific defaults for PIC/PIE
1381e5dd7070Spatrick   if (Triple.isAndroid()) {
1382e5dd7070Spatrick     switch (Triple.getArch()) {
1383e5dd7070Spatrick     case llvm::Triple::arm:
1384e5dd7070Spatrick     case llvm::Triple::armeb:
1385e5dd7070Spatrick     case llvm::Triple::thumb:
1386e5dd7070Spatrick     case llvm::Triple::thumbeb:
1387e5dd7070Spatrick     case llvm::Triple::aarch64:
1388e5dd7070Spatrick     case llvm::Triple::mips:
1389e5dd7070Spatrick     case llvm::Triple::mipsel:
1390e5dd7070Spatrick     case llvm::Triple::mips64:
1391e5dd7070Spatrick     case llvm::Triple::mips64el:
1392e5dd7070Spatrick       PIC = true; // "-fpic"
1393e5dd7070Spatrick       break;
1394e5dd7070Spatrick 
1395e5dd7070Spatrick     case llvm::Triple::x86:
1396e5dd7070Spatrick     case llvm::Triple::x86_64:
1397e5dd7070Spatrick       PIC = true; // "-fPIC"
1398e5dd7070Spatrick       IsPICLevelTwo = true;
1399e5dd7070Spatrick       break;
1400e5dd7070Spatrick 
1401e5dd7070Spatrick     default:
1402e5dd7070Spatrick       break;
1403e5dd7070Spatrick     }
1404e5dd7070Spatrick   }
1405e5dd7070Spatrick 
1406e5dd7070Spatrick   // OpenBSD-specific defaults for PIE
1407e5dd7070Spatrick   if (Triple.isOSOpenBSD()) {
1408e5dd7070Spatrick     switch (ToolChain.getArch()) {
1409e5dd7070Spatrick     case llvm::Triple::arm:
1410e5dd7070Spatrick     case llvm::Triple::aarch64:
1411e5dd7070Spatrick     case llvm::Triple::mips64:
1412e5dd7070Spatrick     case llvm::Triple::mips64el:
1413e5dd7070Spatrick     case llvm::Triple::x86:
1414e5dd7070Spatrick     case llvm::Triple::x86_64:
1415e5dd7070Spatrick       IsPICLevelTwo = false; // "-fpie"
1416e5dd7070Spatrick       break;
1417e5dd7070Spatrick 
1418e5dd7070Spatrick     case llvm::Triple::ppc:
1419e5dd7070Spatrick     case llvm::Triple::sparcv9:
1420e5dd7070Spatrick       IsPICLevelTwo = true; // "-fPIE"
1421e5dd7070Spatrick       break;
1422e5dd7070Spatrick 
1423e5dd7070Spatrick     default:
1424e5dd7070Spatrick       break;
1425e5dd7070Spatrick     }
1426e5dd7070Spatrick   }
1427e5dd7070Spatrick 
1428e5dd7070Spatrick   // AMDGPU-specific defaults for PIC.
1429e5dd7070Spatrick   if (Triple.getArch() == llvm::Triple::amdgcn)
1430e5dd7070Spatrick     PIC = true;
1431e5dd7070Spatrick 
1432e5dd7070Spatrick   // The last argument relating to either PIC or PIE wins, and no
1433e5dd7070Spatrick   // other argument is used. If the last argument is any flavor of the
1434e5dd7070Spatrick   // '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
1435e5dd7070Spatrick   // option implicitly enables PIC at the same level.
1436e5dd7070Spatrick   Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
1437e5dd7070Spatrick                                     options::OPT_fpic, options::OPT_fno_pic,
1438e5dd7070Spatrick                                     options::OPT_fPIE, options::OPT_fno_PIE,
1439e5dd7070Spatrick                                     options::OPT_fpie, options::OPT_fno_pie);
1440*12c85518Srobert   if (Triple.isOSWindows() && !Triple.isOSCygMing() && LastPICArg &&
1441*12c85518Srobert       LastPICArg == Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
1442e5dd7070Spatrick                                     options::OPT_fPIE, options::OPT_fpie)) {
1443e5dd7070Spatrick     ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1444e5dd7070Spatrick         << LastPICArg->getSpelling() << Triple.str();
1445e5dd7070Spatrick     if (Triple.getArch() == llvm::Triple::x86_64)
1446e5dd7070Spatrick       return std::make_tuple(llvm::Reloc::PIC_, 2U, false);
1447e5dd7070Spatrick     return std::make_tuple(llvm::Reloc::Static, 0U, false);
1448e5dd7070Spatrick   }
1449e5dd7070Spatrick 
1450e5dd7070Spatrick   // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
1451e5dd7070Spatrick   // is forced, then neither PIC nor PIE flags will have no effect.
1452e5dd7070Spatrick   if (!ToolChain.isPICDefaultForced()) {
1453e5dd7070Spatrick     if (LastPICArg) {
1454e5dd7070Spatrick       Option O = LastPICArg->getOption();
1455e5dd7070Spatrick       if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
1456e5dd7070Spatrick           O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
1457e5dd7070Spatrick         PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
1458e5dd7070Spatrick         PIC =
1459e5dd7070Spatrick             PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
1460e5dd7070Spatrick         IsPICLevelTwo =
1461e5dd7070Spatrick             O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
1462e5dd7070Spatrick       } else {
1463e5dd7070Spatrick         PIE = PIC = false;
1464*12c85518Srobert         if (EffectiveTriple.isPS()) {
1465e5dd7070Spatrick           Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
1466e5dd7070Spatrick           StringRef Model = ModelArg ? ModelArg->getValue() : "";
1467e5dd7070Spatrick           if (Model != "kernel") {
1468e5dd7070Spatrick             PIC = true;
1469*12c85518Srobert             ToolChain.getDriver().Diag(diag::warn_drv_ps_force_pic)
1470*12c85518Srobert                 << LastPICArg->getSpelling()
1471*12c85518Srobert                 << (EffectiveTriple.isPS4() ? "PS4" : "PS5");
1472e5dd7070Spatrick           }
1473e5dd7070Spatrick         }
1474e5dd7070Spatrick       }
1475e5dd7070Spatrick     }
1476e5dd7070Spatrick   }
1477e5dd7070Spatrick 
1478*12c85518Srobert   // Introduce a Darwin and PS4/PS5-specific hack. If the default is PIC, but
1479*12c85518Srobert   // the PIC level would've been set to level 1, force it back to level 2 PIC
1480e5dd7070Spatrick   // instead.
1481*12c85518Srobert   if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS()))
1482e5dd7070Spatrick     IsPICLevelTwo |= ToolChain.isPICDefault();
1483e5dd7070Spatrick 
1484e5dd7070Spatrick   // This kernel flags are a trump-card: they will disable PIC/PIE
1485e5dd7070Spatrick   // generation, independent of the argument order.
1486e5dd7070Spatrick   if (KernelOrKext &&
1487e5dd7070Spatrick       ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
1488*12c85518Srobert        !EffectiveTriple.isWatchOS() && !EffectiveTriple.isDriverKit()))
1489e5dd7070Spatrick     PIC = PIE = false;
1490e5dd7070Spatrick 
1491e5dd7070Spatrick   if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
1492e5dd7070Spatrick     // This is a very special mode. It trumps the other modes, almost no one
1493e5dd7070Spatrick     // uses it, and it isn't even valid on any OS but Darwin.
1494e5dd7070Spatrick     if (!Triple.isOSDarwin())
1495e5dd7070Spatrick       ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1496e5dd7070Spatrick           << A->getSpelling() << Triple.str();
1497e5dd7070Spatrick 
1498e5dd7070Spatrick     // FIXME: Warn when this flag trumps some other PIC or PIE flag.
1499e5dd7070Spatrick 
1500e5dd7070Spatrick     // Only a forced PIC mode can cause the actual compile to have PIC defines
1501e5dd7070Spatrick     // etc., no flags are sufficient. This behavior was selected to closely
1502e5dd7070Spatrick     // match that of llvm-gcc and Apple GCC before that.
1503e5dd7070Spatrick     PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced();
1504e5dd7070Spatrick 
1505e5dd7070Spatrick     return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false);
1506e5dd7070Spatrick   }
1507e5dd7070Spatrick 
1508e5dd7070Spatrick   bool EmbeddedPISupported;
1509e5dd7070Spatrick   switch (Triple.getArch()) {
1510e5dd7070Spatrick     case llvm::Triple::arm:
1511e5dd7070Spatrick     case llvm::Triple::armeb:
1512e5dd7070Spatrick     case llvm::Triple::thumb:
1513e5dd7070Spatrick     case llvm::Triple::thumbeb:
1514e5dd7070Spatrick       EmbeddedPISupported = true;
1515e5dd7070Spatrick       break;
1516e5dd7070Spatrick     default:
1517e5dd7070Spatrick       EmbeddedPISupported = false;
1518e5dd7070Spatrick       break;
1519e5dd7070Spatrick   }
1520e5dd7070Spatrick 
1521e5dd7070Spatrick   bool ROPI = false, RWPI = false;
1522e5dd7070Spatrick   Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi);
1523e5dd7070Spatrick   if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) {
1524e5dd7070Spatrick     if (!EmbeddedPISupported)
1525e5dd7070Spatrick       ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1526e5dd7070Spatrick           << LastROPIArg->getSpelling() << Triple.str();
1527e5dd7070Spatrick     ROPI = true;
1528e5dd7070Spatrick   }
1529e5dd7070Spatrick   Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi);
1530e5dd7070Spatrick   if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) {
1531e5dd7070Spatrick     if (!EmbeddedPISupported)
1532e5dd7070Spatrick       ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1533e5dd7070Spatrick           << LastRWPIArg->getSpelling() << Triple.str();
1534e5dd7070Spatrick     RWPI = true;
1535e5dd7070Spatrick   }
1536e5dd7070Spatrick 
1537e5dd7070Spatrick   // ROPI and RWPI are not compatible with PIC or PIE.
1538e5dd7070Spatrick   if ((ROPI || RWPI) && (PIC || PIE))
1539e5dd7070Spatrick     ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic);
1540e5dd7070Spatrick 
1541e5dd7070Spatrick   if (Triple.isMIPS()) {
1542e5dd7070Spatrick     StringRef CPUName;
1543e5dd7070Spatrick     StringRef ABIName;
1544e5dd7070Spatrick     mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
1545e5dd7070Spatrick     // When targeting the N64 ABI, PIC is the default, except in the case
1546e5dd7070Spatrick     // when the -mno-abicalls option is used. In that case we exit
1547e5dd7070Spatrick     // at next check regardless of PIC being set below.
1548e5dd7070Spatrick     if (ABIName == "n64")
1549e5dd7070Spatrick       PIC = true;
1550e5dd7070Spatrick     // When targettng MIPS with -mno-abicalls, it's always static.
1551e5dd7070Spatrick     if(Args.hasArg(options::OPT_mno_abicalls))
1552e5dd7070Spatrick       return std::make_tuple(llvm::Reloc::Static, 0U, false);
1553e5dd7070Spatrick     // Unlike other architectures, MIPS, even with -fPIC/-mxgot/multigot,
1554e5dd7070Spatrick     // does not use PIC level 2 for historical reasons.
1555e5dd7070Spatrick     IsPICLevelTwo = false;
1556e5dd7070Spatrick   }
1557e5dd7070Spatrick 
1558e5dd7070Spatrick   if (PIC)
1559e5dd7070Spatrick     return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE);
1560e5dd7070Spatrick 
1561e5dd7070Spatrick   llvm::Reloc::Model RelocM = llvm::Reloc::Static;
1562e5dd7070Spatrick   if (ROPI && RWPI)
1563e5dd7070Spatrick     RelocM = llvm::Reloc::ROPI_RWPI;
1564e5dd7070Spatrick   else if (ROPI)
1565e5dd7070Spatrick     RelocM = llvm::Reloc::ROPI;
1566e5dd7070Spatrick   else if (RWPI)
1567e5dd7070Spatrick     RelocM = llvm::Reloc::RWPI;
1568e5dd7070Spatrick 
1569e5dd7070Spatrick   return std::make_tuple(RelocM, 0U, false);
1570e5dd7070Spatrick }
1571e5dd7070Spatrick 
1572e5dd7070Spatrick // `-falign-functions` indicates that the functions should be aligned to a
1573e5dd7070Spatrick // 16-byte boundary.
1574e5dd7070Spatrick //
1575e5dd7070Spatrick // `-falign-functions=1` is the same as `-fno-align-functions`.
1576e5dd7070Spatrick //
1577e5dd7070Spatrick // The scalar `n` in `-falign-functions=n` must be an integral value between
1578e5dd7070Spatrick // [0, 65536].  If the value is not a power-of-two, it will be rounded up to
1579e5dd7070Spatrick // the nearest power-of-two.
1580e5dd7070Spatrick //
1581e5dd7070Spatrick // If we return `0`, the frontend will default to the backend's preferred
1582e5dd7070Spatrick // alignment.
1583e5dd7070Spatrick //
1584e5dd7070Spatrick // NOTE: icc only allows values between [0, 4096].  icc uses `-falign-functions`
1585e5dd7070Spatrick // to mean `-falign-functions=16`.  GCC defaults to the backend's preferred
1586e5dd7070Spatrick // alignment.  For unaligned functions, we default to the backend's preferred
1587e5dd7070Spatrick // alignment.
ParseFunctionAlignment(const ToolChain & TC,const ArgList & Args)1588e5dd7070Spatrick unsigned tools::ParseFunctionAlignment(const ToolChain &TC,
1589e5dd7070Spatrick                                        const ArgList &Args) {
1590e5dd7070Spatrick   const Arg *A = Args.getLastArg(options::OPT_falign_functions,
1591e5dd7070Spatrick                                  options::OPT_falign_functions_EQ,
1592e5dd7070Spatrick                                  options::OPT_fno_align_functions);
1593e5dd7070Spatrick   if (!A || A->getOption().matches(options::OPT_fno_align_functions))
1594e5dd7070Spatrick     return 0;
1595e5dd7070Spatrick 
1596e5dd7070Spatrick   if (A->getOption().matches(options::OPT_falign_functions))
1597e5dd7070Spatrick     return 0;
1598e5dd7070Spatrick 
1599e5dd7070Spatrick   unsigned Value = 0;
1600e5dd7070Spatrick   if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536)
1601e5dd7070Spatrick     TC.getDriver().Diag(diag::err_drv_invalid_int_value)
1602e5dd7070Spatrick         << A->getAsString(Args) << A->getValue();
1603e5dd7070Spatrick   return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value;
1604e5dd7070Spatrick }
1605e5dd7070Spatrick 
ParseDebugDefaultVersion(const ToolChain & TC,const ArgList & Args)1606*12c85518Srobert static unsigned ParseDebugDefaultVersion(const ToolChain &TC,
1607e5dd7070Spatrick                                          const ArgList &Args) {
1608e5dd7070Spatrick   const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version);
1609e5dd7070Spatrick 
1610e5dd7070Spatrick   if (!A)
1611e5dd7070Spatrick     return 0;
1612e5dd7070Spatrick 
1613e5dd7070Spatrick   unsigned Value = 0;
1614e5dd7070Spatrick   if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 5 ||
1615e5dd7070Spatrick       Value < 2)
1616e5dd7070Spatrick     TC.getDriver().Diag(diag::err_drv_invalid_int_value)
1617e5dd7070Spatrick         << A->getAsString(Args) << A->getValue();
1618e5dd7070Spatrick   return Value;
1619e5dd7070Spatrick }
1620e5dd7070Spatrick 
DwarfVersionNum(StringRef ArgValue)1621*12c85518Srobert unsigned tools::DwarfVersionNum(StringRef ArgValue) {
1622*12c85518Srobert   return llvm::StringSwitch<unsigned>(ArgValue)
1623*12c85518Srobert       .Case("-gdwarf-2", 2)
1624*12c85518Srobert       .Case("-gdwarf-3", 3)
1625*12c85518Srobert       .Case("-gdwarf-4", 4)
1626*12c85518Srobert       .Case("-gdwarf-5", 5)
1627*12c85518Srobert       .Default(0);
1628*12c85518Srobert }
1629*12c85518Srobert 
getDwarfNArg(const ArgList & Args)1630*12c85518Srobert const Arg *tools::getDwarfNArg(const ArgList &Args) {
1631*12c85518Srobert   return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
1632*12c85518Srobert                          options::OPT_gdwarf_4, options::OPT_gdwarf_5,
1633*12c85518Srobert                          options::OPT_gdwarf);
1634*12c85518Srobert }
1635*12c85518Srobert 
getDwarfVersion(const ToolChain & TC,const llvm::opt::ArgList & Args)1636*12c85518Srobert unsigned tools::getDwarfVersion(const ToolChain &TC,
1637*12c85518Srobert                                 const llvm::opt::ArgList &Args) {
1638*12c85518Srobert   unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args);
1639*12c85518Srobert   if (const Arg *GDwarfN = getDwarfNArg(Args))
1640*12c85518Srobert     if (int N = DwarfVersionNum(GDwarfN->getSpelling()))
1641*12c85518Srobert       DwarfVersion = N;
1642*12c85518Srobert   if (DwarfVersion == 0) {
1643*12c85518Srobert     DwarfVersion = TC.GetDefaultDwarfVersion();
1644*12c85518Srobert     assert(DwarfVersion && "toolchain default DWARF version must be nonzero");
1645*12c85518Srobert   }
1646*12c85518Srobert   return DwarfVersion;
1647*12c85518Srobert }
1648*12c85518Srobert 
AddAssemblerKPIC(const ToolChain & ToolChain,const ArgList & Args,ArgStringList & CmdArgs)1649e5dd7070Spatrick void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
1650e5dd7070Spatrick                              ArgStringList &CmdArgs) {
1651e5dd7070Spatrick   llvm::Reloc::Model RelocationModel;
1652e5dd7070Spatrick   unsigned PICLevel;
1653e5dd7070Spatrick   bool IsPIE;
1654e5dd7070Spatrick   std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args);
1655e5dd7070Spatrick 
1656e5dd7070Spatrick   if (RelocationModel != llvm::Reloc::Static)
1657e5dd7070Spatrick     CmdArgs.push_back("-KPIC");
1658e5dd7070Spatrick }
1659e5dd7070Spatrick 
1660e5dd7070Spatrick /// Determine whether Objective-C automated reference counting is
1661e5dd7070Spatrick /// enabled.
isObjCAutoRefCount(const ArgList & Args)1662e5dd7070Spatrick bool tools::isObjCAutoRefCount(const ArgList &Args) {
1663e5dd7070Spatrick   return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
1664e5dd7070Spatrick }
1665e5dd7070Spatrick 
1666e5dd7070Spatrick enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
1667e5dd7070Spatrick 
getLibGccType(const ToolChain & TC,const Driver & D,const ArgList & Args)1668a9ac8606Spatrick static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
1669a9ac8606Spatrick                                 const ArgList &Args) {
1670e5dd7070Spatrick   if (Args.hasArg(options::OPT_static_libgcc) ||
1671*12c85518Srobert       Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie) ||
1672*12c85518Srobert       // The Android NDK only provides libunwind.a, not libunwind.so.
1673*12c85518Srobert       TC.getTriple().isAndroid())
1674e5dd7070Spatrick     return LibGccType::StaticLibGcc;
1675a9ac8606Spatrick   if (Args.hasArg(options::OPT_shared_libgcc))
1676a9ac8606Spatrick     return LibGccType::SharedLibGcc;
1677e5dd7070Spatrick   return LibGccType::UnspecifiedLibGcc;
1678e5dd7070Spatrick }
1679e5dd7070Spatrick 
1680e5dd7070Spatrick // Gcc adds libgcc arguments in various ways:
1681e5dd7070Spatrick //
1682e5dd7070Spatrick // gcc <none>:     -lgcc --as-needed -lgcc_s --no-as-needed
1683e5dd7070Spatrick // g++ <none>:                       -lgcc_s               -lgcc
1684e5dd7070Spatrick // gcc shared:                       -lgcc_s               -lgcc
1685e5dd7070Spatrick // g++ shared:                       -lgcc_s               -lgcc
1686e5dd7070Spatrick // gcc static:     -lgcc             -lgcc_eh
1687e5dd7070Spatrick // g++ static:     -lgcc             -lgcc_eh
1688e5dd7070Spatrick // gcc static-pie: -lgcc             -lgcc_eh
1689e5dd7070Spatrick // g++ static-pie: -lgcc             -lgcc_eh
1690e5dd7070Spatrick //
1691e5dd7070Spatrick // Also, certain targets need additional adjustments.
1692e5dd7070Spatrick 
AddUnwindLibrary(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)1693e5dd7070Spatrick static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
1694e5dd7070Spatrick                              ArgStringList &CmdArgs, const ArgList &Args) {
1695e5dd7070Spatrick   ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args);
1696e5dd7070Spatrick   // Targets that don't use unwind libraries.
1697a9ac8606Spatrick   if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) ||
1698a9ac8606Spatrick       TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() ||
1699*12c85518Srobert       TC.getTriple().isWindowsMSVCEnvironment() || UNW == ToolChain::UNW_None)
1700e5dd7070Spatrick     return;
1701e5dd7070Spatrick 
1702a9ac8606Spatrick   LibGccType LGT = getLibGccType(TC, D, Args);
1703e5dd7070Spatrick   bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
1704*12c85518Srobert                   (UNW == ToolChain::UNW_CompilerRT || !D.CCCIsCXX()) &&
1705a9ac8606Spatrick                   !TC.getTriple().isAndroid() &&
1706a9ac8606Spatrick                   !TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
1707e5dd7070Spatrick   if (AsNeeded)
1708a9ac8606Spatrick     CmdArgs.push_back(getAsNeededOption(TC, true));
1709e5dd7070Spatrick 
1710e5dd7070Spatrick   switch (UNW) {
1711e5dd7070Spatrick   case ToolChain::UNW_None:
1712e5dd7070Spatrick     return;
1713e5dd7070Spatrick   case ToolChain::UNW_Libgcc: {
1714e5dd7070Spatrick     if (LGT == LibGccType::StaticLibGcc)
1715e5dd7070Spatrick       CmdArgs.push_back("-lgcc_eh");
1716e5dd7070Spatrick     else
1717e5dd7070Spatrick       CmdArgs.push_back("-lgcc_s");
1718e5dd7070Spatrick     break;
1719e5dd7070Spatrick   }
1720e5dd7070Spatrick   case ToolChain::UNW_CompilerRT:
1721a9ac8606Spatrick     if (TC.getTriple().isOSAIX()) {
1722a9ac8606Spatrick       // AIX only has libunwind as a shared library. So do not pass
1723a9ac8606Spatrick       // anything in if -static is specified.
1724a9ac8606Spatrick       if (LGT != LibGccType::StaticLibGcc)
1725a9ac8606Spatrick         CmdArgs.push_back("-lunwind");
1726a9ac8606Spatrick     } else if (LGT == LibGccType::StaticLibGcc) {
1727e5dd7070Spatrick       CmdArgs.push_back("-l:libunwind.a");
1728*12c85518Srobert     } else if (LGT == LibGccType::SharedLibGcc) {
1729*12c85518Srobert       if (TC.getTriple().isOSCygMing())
1730ec727ea7Spatrick         CmdArgs.push_back("-l:libunwind.dll.a");
1731e5dd7070Spatrick       else
1732*12c85518Srobert         CmdArgs.push_back("-l:libunwind.so");
1733*12c85518Srobert     } else {
1734*12c85518Srobert       // Let the linker choose between libunwind.so and libunwind.a
1735ec727ea7Spatrick       // depending on what's available, and depending on the -static flag
1736ec727ea7Spatrick       CmdArgs.push_back("-lunwind");
1737a9ac8606Spatrick     }
1738e5dd7070Spatrick     break;
1739e5dd7070Spatrick   }
1740e5dd7070Spatrick 
1741e5dd7070Spatrick   if (AsNeeded)
1742a9ac8606Spatrick     CmdArgs.push_back(getAsNeededOption(TC, false));
1743e5dd7070Spatrick }
1744e5dd7070Spatrick 
AddLibgcc(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)1745e5dd7070Spatrick static void AddLibgcc(const ToolChain &TC, const Driver &D,
1746e5dd7070Spatrick                       ArgStringList &CmdArgs, const ArgList &Args) {
1747a9ac8606Spatrick   LibGccType LGT = getLibGccType(TC, D, Args);
1748*12c85518Srobert   if (LGT == LibGccType::StaticLibGcc ||
1749*12c85518Srobert       (LGT == LibGccType::UnspecifiedLibGcc && !D.CCCIsCXX()))
1750e5dd7070Spatrick     CmdArgs.push_back("-lgcc");
1751e5dd7070Spatrick   AddUnwindLibrary(TC, D, CmdArgs, Args);
1752*12c85518Srobert   if (LGT == LibGccType::SharedLibGcc ||
1753*12c85518Srobert       (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX()))
1754e5dd7070Spatrick     CmdArgs.push_back("-lgcc");
1755e5dd7070Spatrick }
1756e5dd7070Spatrick 
AddRunTimeLibs(const ToolChain & TC,const Driver & D,ArgStringList & CmdArgs,const ArgList & Args)1757e5dd7070Spatrick void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
1758e5dd7070Spatrick                            ArgStringList &CmdArgs, const ArgList &Args) {
1759e5dd7070Spatrick   // Make use of compiler-rt if --rtlib option is used
1760e5dd7070Spatrick   ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);
1761e5dd7070Spatrick 
1762e5dd7070Spatrick   switch (RLT) {
1763e5dd7070Spatrick   case ToolChain::RLT_CompilerRT:
1764e5dd7070Spatrick     CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
1765e5dd7070Spatrick     AddUnwindLibrary(TC, D, CmdArgs, Args);
1766e5dd7070Spatrick     break;
1767e5dd7070Spatrick   case ToolChain::RLT_Libgcc:
1768e5dd7070Spatrick     // Make sure libgcc is not used under MSVC environment by default
1769e5dd7070Spatrick     if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
1770e5dd7070Spatrick       // Issue error diagnostic if libgcc is explicitly specified
1771e5dd7070Spatrick       // through command line as --rtlib option argument.
1772*12c85518Srobert       Arg *A = Args.getLastArg(options::OPT_rtlib_EQ);
1773*12c85518Srobert       if (A && A->getValue() != StringRef("platform")) {
1774e5dd7070Spatrick         TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
1775*12c85518Srobert             << A->getValue() << "MSVC";
1776e5dd7070Spatrick       }
1777e5dd7070Spatrick     } else
1778e5dd7070Spatrick       AddLibgcc(TC, D, CmdArgs, Args);
1779e5dd7070Spatrick     break;
1780e5dd7070Spatrick   }
1781a9ac8606Spatrick 
1782a9ac8606Spatrick   // On Android, the unwinder uses dl_iterate_phdr (or one of
1783a9ac8606Spatrick   // dl_unwind_find_exidx/__gnu_Unwind_Find_exidx on arm32) from libdl.so. For
1784a9ac8606Spatrick   // statically-linked executables, these functions come from libc.a instead.
1785a9ac8606Spatrick   if (TC.getTriple().isAndroid() && !Args.hasArg(options::OPT_static) &&
1786a9ac8606Spatrick       !Args.hasArg(options::OPT_static_pie))
1787a9ac8606Spatrick     CmdArgs.push_back("-ldl");
1788e5dd7070Spatrick }
1789e5dd7070Spatrick 
getStatsFileName(const llvm::opt::ArgList & Args,const InputInfo & Output,const InputInfo & Input,const Driver & D)1790e5dd7070Spatrick SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
1791e5dd7070Spatrick                                          const InputInfo &Output,
1792e5dd7070Spatrick                                          const InputInfo &Input,
1793e5dd7070Spatrick                                          const Driver &D) {
1794e5dd7070Spatrick   const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ);
1795e5dd7070Spatrick   if (!A)
1796e5dd7070Spatrick     return {};
1797e5dd7070Spatrick 
1798e5dd7070Spatrick   StringRef SaveStats = A->getValue();
1799e5dd7070Spatrick   SmallString<128> StatsFile;
1800e5dd7070Spatrick   if (SaveStats == "obj" && Output.isFilename()) {
1801e5dd7070Spatrick     StatsFile.assign(Output.getFilename());
1802e5dd7070Spatrick     llvm::sys::path::remove_filename(StatsFile);
1803e5dd7070Spatrick   } else if (SaveStats != "cwd") {
1804e5dd7070Spatrick     D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
1805e5dd7070Spatrick     return {};
1806e5dd7070Spatrick   }
1807e5dd7070Spatrick 
1808e5dd7070Spatrick   StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
1809e5dd7070Spatrick   llvm::sys::path::append(StatsFile, BaseName);
1810e5dd7070Spatrick   llvm::sys::path::replace_extension(StatsFile, "stats");
1811e5dd7070Spatrick   return StatsFile;
1812e5dd7070Spatrick }
1813e5dd7070Spatrick 
addMultilibFlag(bool Enabled,const char * const Flag,Multilib::flags_list & Flags)1814e5dd7070Spatrick void tools::addMultilibFlag(bool Enabled, const char *const Flag,
1815e5dd7070Spatrick                             Multilib::flags_list &Flags) {
1816e5dd7070Spatrick   Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
1817e5dd7070Spatrick }
1818ec727ea7Spatrick 
addX86AlignBranchArgs(const Driver & D,const ArgList & Args,ArgStringList & CmdArgs,bool IsLTO,const StringRef PluginOptPrefix)1819ec727ea7Spatrick void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
1820*12c85518Srobert                                   ArgStringList &CmdArgs, bool IsLTO,
1821*12c85518Srobert                                   const StringRef PluginOptPrefix) {
1822ec727ea7Spatrick   auto addArg = [&, IsLTO](const Twine &Arg) {
1823ec727ea7Spatrick     if (IsLTO) {
1824*12c85518Srobert       assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
1825*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
1826ec727ea7Spatrick     } else {
1827ec727ea7Spatrick       CmdArgs.push_back("-mllvm");
1828ec727ea7Spatrick       CmdArgs.push_back(Args.MakeArgString(Arg));
1829ec727ea7Spatrick     }
1830ec727ea7Spatrick   };
1831ec727ea7Spatrick 
1832ec727ea7Spatrick   if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) {
1833ec727ea7Spatrick     addArg(Twine("-x86-branches-within-32B-boundaries"));
1834ec727ea7Spatrick   }
1835ec727ea7Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) {
1836ec727ea7Spatrick     StringRef Value = A->getValue();
1837ec727ea7Spatrick     unsigned Boundary;
1838ec727ea7Spatrick     if (Value.getAsInteger(10, Boundary) || Boundary < 16 ||
1839ec727ea7Spatrick         !llvm::isPowerOf2_64(Boundary)) {
1840ec727ea7Spatrick       D.Diag(diag::err_drv_invalid_argument_to_option)
1841ec727ea7Spatrick           << Value << A->getOption().getName();
1842ec727ea7Spatrick     } else {
1843ec727ea7Spatrick       addArg("-x86-align-branch-boundary=" + Twine(Boundary));
1844ec727ea7Spatrick     }
1845ec727ea7Spatrick   }
1846ec727ea7Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) {
1847ec727ea7Spatrick     std::string AlignBranch;
1848ec727ea7Spatrick     for (StringRef T : A->getValues()) {
1849ec727ea7Spatrick       if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" &&
1850ec727ea7Spatrick           T != "ret" && T != "indirect")
1851ec727ea7Spatrick         D.Diag(diag::err_drv_invalid_malign_branch_EQ)
1852ec727ea7Spatrick             << T << "fused, jcc, jmp, call, ret, indirect";
1853ec727ea7Spatrick       if (!AlignBranch.empty())
1854ec727ea7Spatrick         AlignBranch += '+';
1855ec727ea7Spatrick       AlignBranch += T;
1856ec727ea7Spatrick     }
1857ec727ea7Spatrick     addArg("-x86-align-branch=" + Twine(AlignBranch));
1858ec727ea7Spatrick   }
1859ec727ea7Spatrick   if (const Arg *A = Args.getLastArg(options::OPT_mpad_max_prefix_size_EQ)) {
1860ec727ea7Spatrick     StringRef Value = A->getValue();
1861ec727ea7Spatrick     unsigned PrefixSize;
1862ec727ea7Spatrick     if (Value.getAsInteger(10, PrefixSize)) {
1863ec727ea7Spatrick       D.Diag(diag::err_drv_invalid_argument_to_option)
1864ec727ea7Spatrick           << Value << A->getOption().getName();
1865ec727ea7Spatrick     } else {
1866ec727ea7Spatrick       addArg("-x86-pad-max-prefix-size=" + Twine(PrefixSize));
1867ec727ea7Spatrick     }
1868ec727ea7Spatrick   }
1869ec727ea7Spatrick }
1870a9ac8606Spatrick 
1871*12c85518Srobert /// SDLSearch: Search for Static Device Library
1872*12c85518Srobert /// The search for SDL bitcode files is consistent with how static host
1873*12c85518Srobert /// libraries are discovered. That is, the -l option triggers a search for
1874*12c85518Srobert /// files in a set of directories called the LINKPATH. The host library search
1875*12c85518Srobert /// procedure looks for a specific filename in the LINKPATH.  The filename for
1876*12c85518Srobert /// a host library is lib<libname>.a or lib<libname>.so. For SDLs, there is an
1877*12c85518Srobert /// ordered-set of filenames that are searched. We call this ordered-set of
1878*12c85518Srobert /// filenames as SEARCH-ORDER. Since an SDL can either be device-type specific,
1879*12c85518Srobert /// architecture specific, or generic across all architectures, a naming
1880*12c85518Srobert /// convention and search order is used where the file name embeds the
1881*12c85518Srobert /// architecture name <arch-name> (nvptx or amdgcn) and the GPU device type
1882*12c85518Srobert /// <device-name> such as sm_30 and gfx906. <device-name> is absent in case of
1883*12c85518Srobert /// device-independent SDLs. To reduce congestion in host library directories,
1884*12c85518Srobert /// the search first looks for files in the “libdevice” subdirectory. SDLs that
1885*12c85518Srobert /// are bc files begin with the prefix “lib”.
1886*12c85518Srobert ///
1887*12c85518Srobert /// Machine-code SDLs can also be managed as an archive (*.a file). The
1888*12c85518Srobert /// convention has been to use the prefix “lib”. To avoid confusion with host
1889*12c85518Srobert /// archive libraries, we use prefix "libbc-" for the bitcode SDL archives.
1890*12c85518Srobert ///
SDLSearch(const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,SmallVector<std::string,8> LibraryPaths,std::string Lib,StringRef Arch,StringRef Target,bool isBitCodeSDL,bool postClangLink)1891*12c85518Srobert bool tools::SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs,
1892*12c85518Srobert                       llvm::opt::ArgStringList &CC1Args,
1893*12c85518Srobert                       SmallVector<std::string, 8> LibraryPaths, std::string Lib,
1894*12c85518Srobert                       StringRef Arch, StringRef Target, bool isBitCodeSDL,
1895*12c85518Srobert                       bool postClangLink) {
1896*12c85518Srobert   SmallVector<std::string, 12> SDLs;
1897*12c85518Srobert 
1898*12c85518Srobert   std::string LibDeviceLoc = "/libdevice";
1899*12c85518Srobert   std::string LibBcPrefix = "/libbc-";
1900*12c85518Srobert   std::string LibPrefix = "/lib";
1901*12c85518Srobert 
1902*12c85518Srobert   if (isBitCodeSDL) {
1903*12c85518Srobert     // SEARCH-ORDER for Bitcode SDLs:
1904*12c85518Srobert     //       libdevice/libbc-<libname>-<arch-name>-<device-type>.a
1905*12c85518Srobert     //       libbc-<libname>-<arch-name>-<device-type>.a
1906*12c85518Srobert     //       libdevice/libbc-<libname>-<arch-name>.a
1907*12c85518Srobert     //       libbc-<libname>-<arch-name>.a
1908*12c85518Srobert     //       libdevice/libbc-<libname>.a
1909*12c85518Srobert     //       libbc-<libname>.a
1910*12c85518Srobert     //       libdevice/lib<libname>-<arch-name>-<device-type>.bc
1911*12c85518Srobert     //       lib<libname>-<arch-name>-<device-type>.bc
1912*12c85518Srobert     //       libdevice/lib<libname>-<arch-name>.bc
1913*12c85518Srobert     //       lib<libname>-<arch-name>.bc
1914*12c85518Srobert     //       libdevice/lib<libname>.bc
1915*12c85518Srobert     //       lib<libname>.bc
1916*12c85518Srobert 
1917*12c85518Srobert     for (StringRef Base : {LibBcPrefix, LibPrefix}) {
1918*12c85518Srobert       const auto *Ext = Base.contains(LibBcPrefix) ? ".a" : ".bc";
1919*12c85518Srobert 
1920*12c85518Srobert       for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
1921*12c85518Srobert                           Twine(Lib + "-" + Arch).str(), Twine(Lib).str()}) {
1922*12c85518Srobert         SDLs.push_back(Twine(LibDeviceLoc + Base + Suffix + Ext).str());
1923*12c85518Srobert         SDLs.push_back(Twine(Base + Suffix + Ext).str());
1924*12c85518Srobert       }
1925*12c85518Srobert     }
1926*12c85518Srobert   } else {
1927*12c85518Srobert     // SEARCH-ORDER for Machine-code SDLs:
1928*12c85518Srobert     //    libdevice/lib<libname>-<arch-name>-<device-type>.a
1929*12c85518Srobert     //    lib<libname>-<arch-name>-<device-type>.a
1930*12c85518Srobert     //    libdevice/lib<libname>-<arch-name>.a
1931*12c85518Srobert     //    lib<libname>-<arch-name>.a
1932*12c85518Srobert 
1933*12c85518Srobert     const auto *Ext = ".a";
1934*12c85518Srobert 
1935*12c85518Srobert     for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
1936*12c85518Srobert                         Twine(Lib + "-" + Arch).str()}) {
1937*12c85518Srobert       SDLs.push_back(Twine(LibDeviceLoc + LibPrefix + Suffix + Ext).str());
1938*12c85518Srobert       SDLs.push_back(Twine(LibPrefix + Suffix + Ext).str());
1939*12c85518Srobert     }
1940*12c85518Srobert   }
1941*12c85518Srobert 
1942*12c85518Srobert   // The CUDA toolchain does not use a global device llvm-link before the LLVM
1943*12c85518Srobert   // backend generates ptx. So currently, the use of bitcode SDL for nvptx is
1944*12c85518Srobert   // only possible with post-clang-cc1 linking. Clang cc1 has a feature that
1945*12c85518Srobert   // will link libraries after clang compilation while the LLVM IR is still in
1946*12c85518Srobert   // memory. This utilizes a clang cc1 option called “-mlink-builtin-bitcode”.
1947*12c85518Srobert   // This is a clang -cc1 option that is generated by the clang driver. The
1948*12c85518Srobert   // option value must a full path to an existing file.
1949*12c85518Srobert   bool FoundSDL = false;
1950*12c85518Srobert   for (auto LPath : LibraryPaths) {
1951*12c85518Srobert     for (auto SDL : SDLs) {
1952*12c85518Srobert       auto FullName = Twine(LPath + SDL).str();
1953*12c85518Srobert       if (llvm::sys::fs::exists(FullName)) {
1954*12c85518Srobert         if (postClangLink)
1955*12c85518Srobert           CC1Args.push_back("-mlink-builtin-bitcode");
1956*12c85518Srobert         CC1Args.push_back(DriverArgs.MakeArgString(FullName));
1957*12c85518Srobert         FoundSDL = true;
1958*12c85518Srobert         break;
1959*12c85518Srobert       }
1960*12c85518Srobert     }
1961*12c85518Srobert     if (FoundSDL)
1962*12c85518Srobert       break;
1963*12c85518Srobert   }
1964*12c85518Srobert   return FoundSDL;
1965*12c85518Srobert }
1966*12c85518Srobert 
1967*12c85518Srobert /// Search if a user provided archive file lib<libname>.a exists in any of
1968*12c85518Srobert /// the library paths. If so, add a new command to clang-offload-bundler to
1969*12c85518Srobert /// unbundle this archive and create a temporary device specific archive. Name
1970*12c85518Srobert /// of this SDL is passed to the llvm-link tool.
GetSDLFromOffloadArchive(Compilation & C,const Driver & D,const Tool & T,const JobAction & JA,const InputInfoList & Inputs,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,SmallVector<std::string,8> LibraryPaths,StringRef Lib,StringRef Arch,StringRef Target,bool isBitCodeSDL,bool postClangLink)1971*12c85518Srobert bool tools::GetSDLFromOffloadArchive(
1972*12c85518Srobert     Compilation &C, const Driver &D, const Tool &T, const JobAction &JA,
1973*12c85518Srobert     const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs,
1974*12c85518Srobert     llvm::opt::ArgStringList &CC1Args, SmallVector<std::string, 8> LibraryPaths,
1975*12c85518Srobert     StringRef Lib, StringRef Arch, StringRef Target, bool isBitCodeSDL,
1976*12c85518Srobert     bool postClangLink) {
1977*12c85518Srobert 
1978*12c85518Srobert   // We don't support bitcode archive bundles for nvptx
1979*12c85518Srobert   if (isBitCodeSDL && Arch.contains("nvptx"))
1980*12c85518Srobert     return false;
1981*12c85518Srobert 
1982*12c85518Srobert   bool FoundAOB = false;
1983*12c85518Srobert   std::string ArchiveOfBundles;
1984*12c85518Srobert 
1985*12c85518Srobert   llvm::Triple Triple(D.getTargetTriple());
1986*12c85518Srobert   bool IsMSVC = Triple.isWindowsMSVCEnvironment();
1987*12c85518Srobert   auto Ext = IsMSVC ? ".lib" : ".a";
1988*12c85518Srobert   if (!Lib.startswith(":") && !Lib.startswith("-l")) {
1989*12c85518Srobert     if (llvm::sys::fs::exists(Lib)) {
1990*12c85518Srobert       ArchiveOfBundles = Lib;
1991*12c85518Srobert       FoundAOB = true;
1992*12c85518Srobert     }
1993*12c85518Srobert   } else {
1994*12c85518Srobert     if (Lib.startswith("-l"))
1995*12c85518Srobert       Lib = Lib.drop_front(2);
1996*12c85518Srobert     for (auto LPath : LibraryPaths) {
1997*12c85518Srobert       ArchiveOfBundles.clear();
1998*12c85518Srobert       SmallVector<std::string, 2> AOBFileNames;
1999*12c85518Srobert       auto LibFile =
2000*12c85518Srobert           (Lib.startswith(":") ? Lib.drop_front()
2001*12c85518Srobert                                : IsMSVC ? Lib + Ext : "lib" + Lib + Ext)
2002*12c85518Srobert               .str();
2003*12c85518Srobert       for (auto Prefix : {"/libdevice/", "/"}) {
2004*12c85518Srobert         auto AOB = Twine(LPath + Prefix + LibFile).str();
2005*12c85518Srobert         if (llvm::sys::fs::exists(AOB)) {
2006*12c85518Srobert           ArchiveOfBundles = AOB;
2007*12c85518Srobert           FoundAOB = true;
2008*12c85518Srobert           break;
2009*12c85518Srobert         }
2010*12c85518Srobert       }
2011*12c85518Srobert       if (FoundAOB)
2012*12c85518Srobert         break;
2013*12c85518Srobert     }
2014*12c85518Srobert   }
2015*12c85518Srobert 
2016*12c85518Srobert   if (!FoundAOB)
2017*12c85518Srobert     return false;
2018*12c85518Srobert 
2019*12c85518Srobert   llvm::file_magic Magic;
2020*12c85518Srobert   auto EC = llvm::identify_magic(ArchiveOfBundles, Magic);
2021*12c85518Srobert   if (EC || Magic != llvm::file_magic::archive)
2022*12c85518Srobert     return false;
2023*12c85518Srobert 
2024*12c85518Srobert   StringRef Prefix = isBitCodeSDL ? "libbc-" : "lib";
2025*12c85518Srobert   std::string OutputLib =
2026*12c85518Srobert       D.GetTemporaryPath(Twine(Prefix + llvm::sys::path::filename(Lib) + "-" +
2027*12c85518Srobert                                Arch + "-" + Target)
2028*12c85518Srobert                              .str(),
2029*12c85518Srobert                          "a");
2030*12c85518Srobert 
2031*12c85518Srobert   C.addTempFile(C.getArgs().MakeArgString(OutputLib));
2032*12c85518Srobert 
2033*12c85518Srobert   ArgStringList CmdArgs;
2034*12c85518Srobert   SmallString<128> DeviceTriple;
2035*12c85518Srobert   DeviceTriple += Action::GetOffloadKindName(JA.getOffloadingDeviceKind());
2036*12c85518Srobert   DeviceTriple += '-';
2037*12c85518Srobert   std::string NormalizedTriple = T.getToolChain().getTriple().normalize();
2038*12c85518Srobert   DeviceTriple += NormalizedTriple;
2039*12c85518Srobert   if (!Target.empty()) {
2040*12c85518Srobert     DeviceTriple += '-';
2041*12c85518Srobert     DeviceTriple += Target;
2042*12c85518Srobert   }
2043*12c85518Srobert 
2044*12c85518Srobert   std::string UnbundleArg("-unbundle");
2045*12c85518Srobert   std::string TypeArg("-type=a");
2046*12c85518Srobert   std::string InputArg("-input=" + ArchiveOfBundles);
2047*12c85518Srobert   std::string OffloadArg("-targets=" + std::string(DeviceTriple));
2048*12c85518Srobert   std::string OutputArg("-output=" + OutputLib);
2049*12c85518Srobert 
2050*12c85518Srobert   const char *UBProgram = DriverArgs.MakeArgString(
2051*12c85518Srobert       T.getToolChain().GetProgramPath("clang-offload-bundler"));
2052*12c85518Srobert 
2053*12c85518Srobert   ArgStringList UBArgs;
2054*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(UnbundleArg));
2055*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(TypeArg));
2056*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(InputArg));
2057*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(OffloadArg));
2058*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(OutputArg));
2059*12c85518Srobert 
2060*12c85518Srobert   // Add this flag to not exit from clang-offload-bundler if no compatible
2061*12c85518Srobert   // code object is found in heterogenous archive library.
2062*12c85518Srobert   std::string AdditionalArgs("-allow-missing-bundles");
2063*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(AdditionalArgs));
2064*12c85518Srobert 
2065*12c85518Srobert   // Add this flag to treat hip and hipv4 offload kinds as compatible with
2066*12c85518Srobert   // openmp offload kind while extracting code objects from a heterogenous
2067*12c85518Srobert   // archive library. Vice versa is also considered compatible.
2068*12c85518Srobert   std::string HipCompatibleArgs("-hip-openmp-compatible");
2069*12c85518Srobert   UBArgs.push_back(C.getArgs().MakeArgString(HipCompatibleArgs));
2070*12c85518Srobert 
2071*12c85518Srobert   C.addCommand(std::make_unique<Command>(
2072*12c85518Srobert       JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs,
2073*12c85518Srobert       InputInfo(&JA, C.getArgs().MakeArgString(OutputLib))));
2074*12c85518Srobert   if (postClangLink)
2075*12c85518Srobert     CC1Args.push_back("-mlink-builtin-bitcode");
2076*12c85518Srobert 
2077*12c85518Srobert   CC1Args.push_back(DriverArgs.MakeArgString(OutputLib));
2078*12c85518Srobert 
2079*12c85518Srobert   return true;
2080*12c85518Srobert }
2081*12c85518Srobert 
2082*12c85518Srobert // Wrapper function used by driver for adding SDLs during link phase.
AddStaticDeviceLibsLinking(Compilation & C,const Tool & T,const JobAction & JA,const InputInfoList & Inputs,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef Arch,StringRef Target,bool isBitCodeSDL,bool postClangLink)2083*12c85518Srobert void tools::AddStaticDeviceLibsLinking(Compilation &C, const Tool &T,
2084*12c85518Srobert                                 const JobAction &JA,
2085*12c85518Srobert                                 const InputInfoList &Inputs,
2086*12c85518Srobert                                 const llvm::opt::ArgList &DriverArgs,
2087*12c85518Srobert                                 llvm::opt::ArgStringList &CC1Args,
2088*12c85518Srobert                                 StringRef Arch, StringRef Target,
2089*12c85518Srobert                                 bool isBitCodeSDL, bool postClangLink) {
2090*12c85518Srobert   AddStaticDeviceLibs(&C, &T, &JA, &Inputs, C.getDriver(), DriverArgs, CC1Args,
2091*12c85518Srobert                       Arch, Target, isBitCodeSDL, postClangLink);
2092*12c85518Srobert }
2093*12c85518Srobert 
2094*12c85518Srobert // User defined Static Device Libraries(SDLs) can be passed to clang for
2095*12c85518Srobert // offloading GPU compilers. Like static host libraries, the use of a SDL is
2096*12c85518Srobert // specified with the -l command line option. The primary difference between
2097*12c85518Srobert // host and SDLs is the filenames for SDLs (refer SEARCH-ORDER for Bitcode SDLs
2098*12c85518Srobert // and SEARCH-ORDER for Machine-code SDLs for the naming convention).
2099*12c85518Srobert // SDLs are of following types:
2100*12c85518Srobert //
2101*12c85518Srobert // * Bitcode SDLs: They can either be a *.bc file or an archive of *.bc files.
2102*12c85518Srobert //           For NVPTX, these libraries are post-clang linked following each
2103*12c85518Srobert //           compilation. For AMDGPU, these libraries are linked one time
2104*12c85518Srobert //           during the application link phase.
2105*12c85518Srobert //
2106*12c85518Srobert // * Machine-code SDLs: They are archive files. For AMDGPU, the process for
2107*12c85518Srobert //           machine code SDLs is still in development. But they will be linked
2108*12c85518Srobert //           by the LLVM tool lld.
2109*12c85518Srobert //
2110*12c85518Srobert // * Bundled objects that contain both host and device codes: Bundled objects
2111*12c85518Srobert //           may also contain library code compiled from source. For NVPTX, the
2112*12c85518Srobert //           bundle contains cubin. For AMDGPU, the bundle contains bitcode.
2113*12c85518Srobert //
2114*12c85518Srobert // For Bitcode and Machine-code SDLs, current compiler toolchains hardcode the
2115*12c85518Srobert // inclusion of specific SDLs such as math libraries and the OpenMP device
2116*12c85518Srobert // library libomptarget.
AddStaticDeviceLibs(Compilation * C,const Tool * T,const JobAction * JA,const InputInfoList * Inputs,const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef Arch,StringRef Target,bool isBitCodeSDL,bool postClangLink)2117*12c85518Srobert void tools::AddStaticDeviceLibs(Compilation *C, const Tool *T,
2118*12c85518Srobert                                 const JobAction *JA,
2119*12c85518Srobert                                 const InputInfoList *Inputs, const Driver &D,
2120*12c85518Srobert                                 const llvm::opt::ArgList &DriverArgs,
2121*12c85518Srobert                                 llvm::opt::ArgStringList &CC1Args,
2122*12c85518Srobert                                 StringRef Arch, StringRef Target,
2123*12c85518Srobert                                 bool isBitCodeSDL, bool postClangLink) {
2124*12c85518Srobert 
2125*12c85518Srobert   SmallVector<std::string, 8> LibraryPaths;
2126*12c85518Srobert   // Add search directories from LIBRARY_PATH env variable
2127*12c85518Srobert   std::optional<std::string> LibPath =
2128*12c85518Srobert       llvm::sys::Process::GetEnv("LIBRARY_PATH");
2129*12c85518Srobert   if (LibPath) {
2130*12c85518Srobert     SmallVector<StringRef, 8> Frags;
2131*12c85518Srobert     const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
2132*12c85518Srobert     llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
2133*12c85518Srobert     for (StringRef Path : Frags)
2134*12c85518Srobert       LibraryPaths.emplace_back(Path.trim());
2135*12c85518Srobert   }
2136*12c85518Srobert 
2137*12c85518Srobert   // Add directories from user-specified -L options
2138*12c85518Srobert   for (std::string Search_Dir : DriverArgs.getAllArgValues(options::OPT_L))
2139*12c85518Srobert     LibraryPaths.emplace_back(Search_Dir);
2140*12c85518Srobert 
2141*12c85518Srobert   // Add path to lib-debug folders
2142*12c85518Srobert   SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
2143*12c85518Srobert   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
2144*12c85518Srobert   LibraryPaths.emplace_back(DefaultLibPath.c_str());
2145*12c85518Srobert 
2146*12c85518Srobert   // Build list of Static Device Libraries SDLs specified by -l option
2147*12c85518Srobert   llvm::SmallSet<std::string, 16> SDLNames;
2148*12c85518Srobert   static const StringRef HostOnlyArchives[] = {
2149*12c85518Srobert       "omp", "cudart", "m", "gcc", "gcc_s", "pthread", "hip_hcc"};
2150*12c85518Srobert   for (auto SDLName : DriverArgs.getAllArgValues(options::OPT_l)) {
2151*12c85518Srobert     if (!HostOnlyArchives->contains(SDLName)) {
2152*12c85518Srobert       SDLNames.insert(std::string("-l") + SDLName);
2153*12c85518Srobert     }
2154*12c85518Srobert   }
2155*12c85518Srobert 
2156*12c85518Srobert   for (auto Input : DriverArgs.getAllArgValues(options::OPT_INPUT)) {
2157*12c85518Srobert     auto FileName = StringRef(Input);
2158*12c85518Srobert     // Clang treats any unknown file types as archives and passes them to the
2159*12c85518Srobert     // linker. Files with extension 'lib' are classified as TY_Object by clang
2160*12c85518Srobert     // but they are usually archives. It is OK if the file is not really an
2161*12c85518Srobert     // archive since GetSDLFromOffloadArchive will check the magic of the file
2162*12c85518Srobert     // and only unbundle it if it is really an archive.
2163*12c85518Srobert     const StringRef LibFileExt = ".lib";
2164*12c85518Srobert     if (!llvm::sys::path::has_extension(FileName) ||
2165*12c85518Srobert         types::lookupTypeForExtension(
2166*12c85518Srobert             llvm::sys::path::extension(FileName).drop_front()) ==
2167*12c85518Srobert             types::TY_INVALID ||
2168*12c85518Srobert         llvm::sys::path::extension(FileName) == LibFileExt)
2169*12c85518Srobert       SDLNames.insert(Input);
2170*12c85518Srobert   }
2171*12c85518Srobert 
2172*12c85518Srobert   // The search stops as soon as an SDL file is found. The driver then provides
2173*12c85518Srobert   // the full filename of the SDL to the llvm-link command. If no SDL is found
2174*12c85518Srobert   // after searching each LINKPATH with SEARCH-ORDER, it is possible that an
2175*12c85518Srobert   // archive file lib<libname>.a exists and may contain bundled object files.
2176*12c85518Srobert   for (auto SDLName : SDLNames) {
2177*12c85518Srobert     // This is the only call to SDLSearch
2178*12c85518Srobert     if (!SDLSearch(D, DriverArgs, CC1Args, LibraryPaths, SDLName, Arch, Target,
2179*12c85518Srobert                    isBitCodeSDL, postClangLink)) {
2180*12c85518Srobert       GetSDLFromOffloadArchive(*C, D, *T, *JA, *Inputs, DriverArgs, CC1Args,
2181*12c85518Srobert                                LibraryPaths, SDLName, Arch, Target,
2182*12c85518Srobert                                isBitCodeSDL, postClangLink);
2183*12c85518Srobert     }
2184*12c85518Srobert   }
2185*12c85518Srobert }
2186*12c85518Srobert 
2187a9ac8606Spatrick static llvm::opt::Arg *
getAMDGPUCodeObjectArgument(const Driver & D,const llvm::opt::ArgList & Args)2188a9ac8606Spatrick getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
2189a9ac8606Spatrick   // The last of -mcode-object-v3, -mno-code-object-v3 and
2190a9ac8606Spatrick   // -mcode-object-version=<version> wins.
2191a9ac8606Spatrick   return Args.getLastArg(options::OPT_mcode_object_v3_legacy,
2192a9ac8606Spatrick                          options::OPT_mno_code_object_v3_legacy,
2193a9ac8606Spatrick                          options::OPT_mcode_object_version_EQ);
2194a9ac8606Spatrick }
2195a9ac8606Spatrick 
checkAMDGPUCodeObjectVersion(const Driver & D,const llvm::opt::ArgList & Args)2196a9ac8606Spatrick void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
2197a9ac8606Spatrick                                          const llvm::opt::ArgList &Args) {
2198a9ac8606Spatrick   const unsigned MinCodeObjVer = 2;
2199*12c85518Srobert   const unsigned MaxCodeObjVer = 5;
2200a9ac8606Spatrick 
2201a9ac8606Spatrick   // Emit warnings for legacy options even if they are overridden.
2202a9ac8606Spatrick   if (Args.hasArg(options::OPT_mno_code_object_v3_legacy))
2203a9ac8606Spatrick     D.Diag(diag::warn_drv_deprecated_arg) << "-mno-code-object-v3"
2204a9ac8606Spatrick                                           << "-mcode-object-version=2";
2205a9ac8606Spatrick 
2206a9ac8606Spatrick   if (Args.hasArg(options::OPT_mcode_object_v3_legacy))
2207a9ac8606Spatrick     D.Diag(diag::warn_drv_deprecated_arg) << "-mcode-object-v3"
2208a9ac8606Spatrick                                           << "-mcode-object-version=3";
2209a9ac8606Spatrick 
2210a9ac8606Spatrick   if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
2211a9ac8606Spatrick     if (CodeObjArg->getOption().getID() ==
2212a9ac8606Spatrick         options::OPT_mcode_object_version_EQ) {
2213a9ac8606Spatrick       unsigned CodeObjVer = MaxCodeObjVer;
2214a9ac8606Spatrick       auto Remnant =
2215a9ac8606Spatrick           StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
2216a9ac8606Spatrick       if (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer)
2217a9ac8606Spatrick         D.Diag(diag::err_drv_invalid_int_value)
2218a9ac8606Spatrick             << CodeObjArg->getAsString(Args) << CodeObjArg->getValue();
2219a9ac8606Spatrick     }
2220a9ac8606Spatrick   }
2221a9ac8606Spatrick }
2222a9ac8606Spatrick 
getAMDGPUCodeObjectVersion(const Driver & D,const llvm::opt::ArgList & Args)2223a9ac8606Spatrick unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D,
2224a9ac8606Spatrick                                            const llvm::opt::ArgList &Args) {
2225a9ac8606Spatrick   unsigned CodeObjVer = 4; // default
2226a9ac8606Spatrick   if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
2227a9ac8606Spatrick     if (CodeObjArg->getOption().getID() ==
2228a9ac8606Spatrick         options::OPT_mno_code_object_v3_legacy) {
2229a9ac8606Spatrick       CodeObjVer = 2;
2230a9ac8606Spatrick     } else if (CodeObjArg->getOption().getID() ==
2231a9ac8606Spatrick                options::OPT_mcode_object_v3_legacy) {
2232a9ac8606Spatrick       CodeObjVer = 3;
2233a9ac8606Spatrick     } else {
2234a9ac8606Spatrick       StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
2235a9ac8606Spatrick     }
2236a9ac8606Spatrick   }
2237a9ac8606Spatrick   return CodeObjVer;
2238a9ac8606Spatrick }
2239a9ac8606Spatrick 
haveAMDGPUCodeObjectVersionArgument(const Driver & D,const llvm::opt::ArgList & Args)2240a9ac8606Spatrick bool tools::haveAMDGPUCodeObjectVersionArgument(
2241a9ac8606Spatrick     const Driver &D, const llvm::opt::ArgList &Args) {
2242a9ac8606Spatrick   return getAMDGPUCodeObjectArgument(D, Args) != nullptr;
2243a9ac8606Spatrick }
2244a9ac8606Spatrick 
addMachineOutlinerArgs(const Driver & D,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs,const llvm::Triple & Triple,bool IsLTO,const StringRef PluginOptPrefix)2245a9ac8606Spatrick void tools::addMachineOutlinerArgs(const Driver &D,
2246a9ac8606Spatrick                                    const llvm::opt::ArgList &Args,
2247a9ac8606Spatrick                                    llvm::opt::ArgStringList &CmdArgs,
2248*12c85518Srobert                                    const llvm::Triple &Triple, bool IsLTO,
2249*12c85518Srobert                                    const StringRef PluginOptPrefix) {
2250a9ac8606Spatrick   auto addArg = [&, IsLTO](const Twine &Arg) {
2251a9ac8606Spatrick     if (IsLTO) {
2252*12c85518Srobert       assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
2253*12c85518Srobert       CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
2254a9ac8606Spatrick     } else {
2255a9ac8606Spatrick       CmdArgs.push_back("-mllvm");
2256a9ac8606Spatrick       CmdArgs.push_back(Args.MakeArgString(Arg));
2257a9ac8606Spatrick     }
2258a9ac8606Spatrick   };
2259a9ac8606Spatrick 
2260a9ac8606Spatrick   if (Arg *A = Args.getLastArg(options::OPT_moutline,
2261a9ac8606Spatrick                                options::OPT_mno_outline)) {
2262a9ac8606Spatrick     if (A->getOption().matches(options::OPT_moutline)) {
2263a9ac8606Spatrick       // We only support -moutline in AArch64 and ARM targets right now. If
2264a9ac8606Spatrick       // we're not compiling for these, emit a warning and ignore the flag.
2265a9ac8606Spatrick       // Otherwise, add the proper mllvm flags.
2266a9ac8606Spatrick       if (!(Triple.isARM() || Triple.isThumb() ||
2267a9ac8606Spatrick             Triple.getArch() == llvm::Triple::aarch64 ||
2268a9ac8606Spatrick             Triple.getArch() == llvm::Triple::aarch64_32)) {
2269a9ac8606Spatrick         D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
2270a9ac8606Spatrick       } else {
2271a9ac8606Spatrick         addArg(Twine("-enable-machine-outliner"));
2272a9ac8606Spatrick       }
2273a9ac8606Spatrick     } else {
2274a9ac8606Spatrick       // Disable all outlining behaviour.
2275a9ac8606Spatrick       addArg(Twine("-enable-machine-outliner=never"));
2276a9ac8606Spatrick     }
2277a9ac8606Spatrick   }
2278a9ac8606Spatrick }
2279a9ac8606Spatrick 
addOpenMPDeviceRTL(const Driver & D,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef BitcodeSuffix,const llvm::Triple & Triple)2280a9ac8606Spatrick void tools::addOpenMPDeviceRTL(const Driver &D,
2281a9ac8606Spatrick                                const llvm::opt::ArgList &DriverArgs,
2282a9ac8606Spatrick                                llvm::opt::ArgStringList &CC1Args,
2283a9ac8606Spatrick                                StringRef BitcodeSuffix,
2284a9ac8606Spatrick                                const llvm::Triple &Triple) {
2285a9ac8606Spatrick   SmallVector<StringRef, 8> LibraryPaths;
2286*12c85518Srobert 
2287*12c85518Srobert   // Add path to clang lib / lib64 folder.
2288*12c85518Srobert   SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
2289*12c85518Srobert   llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
2290*12c85518Srobert   LibraryPaths.emplace_back(DefaultLibPath.c_str());
2291*12c85518Srobert 
2292a9ac8606Spatrick   // Add user defined library paths from LIBRARY_PATH.
2293*12c85518Srobert   std::optional<std::string> LibPath =
2294a9ac8606Spatrick       llvm::sys::Process::GetEnv("LIBRARY_PATH");
2295a9ac8606Spatrick   if (LibPath) {
2296a9ac8606Spatrick     SmallVector<StringRef, 8> Frags;
2297a9ac8606Spatrick     const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
2298a9ac8606Spatrick     llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
2299a9ac8606Spatrick     for (StringRef Path : Frags)
2300a9ac8606Spatrick       LibraryPaths.emplace_back(Path.trim());
2301a9ac8606Spatrick   }
2302a9ac8606Spatrick 
2303a9ac8606Spatrick   OptSpecifier LibomptargetBCPathOpt =
2304*12c85518Srobert       Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
2305a9ac8606Spatrick                         : options::OPT_libomptarget_nvptx_bc_path_EQ;
2306a9ac8606Spatrick 
2307*12c85518Srobert   StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx";
2308*12c85518Srobert   std::string LibOmpTargetName =
2309*12c85518Srobert       ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str();
2310*12c85518Srobert 
2311a9ac8606Spatrick   // First check whether user specifies bc library
2312a9ac8606Spatrick   if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
2313*12c85518Srobert     SmallString<128> LibOmpTargetFile(A->getValue());
2314*12c85518Srobert     if (llvm::sys::fs::exists(LibOmpTargetFile) &&
2315*12c85518Srobert         llvm::sys::fs::is_directory(LibOmpTargetFile)) {
2316*12c85518Srobert       llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
2317*12c85518Srobert     }
2318*12c85518Srobert 
2319*12c85518Srobert     if (llvm::sys::fs::exists(LibOmpTargetFile)) {
2320a9ac8606Spatrick       CC1Args.push_back("-mlink-builtin-bitcode");
2321*12c85518Srobert       CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
2322a9ac8606Spatrick     } else {
2323a9ac8606Spatrick       D.Diag(diag::err_drv_omp_offload_target_bcruntime_not_found)
2324*12c85518Srobert           << LibOmpTargetFile;
2325a9ac8606Spatrick     }
2326a9ac8606Spatrick   } else {
2327a9ac8606Spatrick     bool FoundBCLibrary = false;
2328a9ac8606Spatrick 
2329a9ac8606Spatrick     for (StringRef LibraryPath : LibraryPaths) {
2330a9ac8606Spatrick       SmallString<128> LibOmpTargetFile(LibraryPath);
2331a9ac8606Spatrick       llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
2332a9ac8606Spatrick       if (llvm::sys::fs::exists(LibOmpTargetFile)) {
2333a9ac8606Spatrick         CC1Args.push_back("-mlink-builtin-bitcode");
2334a9ac8606Spatrick         CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
2335a9ac8606Spatrick         FoundBCLibrary = true;
2336a9ac8606Spatrick         break;
2337a9ac8606Spatrick       }
2338a9ac8606Spatrick     }
2339a9ac8606Spatrick 
2340a9ac8606Spatrick     if (!FoundBCLibrary)
2341a9ac8606Spatrick       D.Diag(diag::err_drv_omp_offload_target_missingbcruntime)
2342a9ac8606Spatrick           << LibOmpTargetName << ArchPrefix;
2343a9ac8606Spatrick   }
2344a9ac8606Spatrick }
addHIPRuntimeLibArgs(const ToolChain & TC,const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)2345*12c85518Srobert void tools::addHIPRuntimeLibArgs(const ToolChain &TC,
2346*12c85518Srobert                                  const llvm::opt::ArgList &Args,
2347*12c85518Srobert                                  llvm::opt::ArgStringList &CmdArgs) {
2348*12c85518Srobert   if (Args.hasArg(options::OPT_hip_link) &&
2349*12c85518Srobert       !Args.hasArg(options::OPT_nostdlib) &&
2350*12c85518Srobert       !Args.hasArg(options::OPT_no_hip_rt)) {
2351*12c85518Srobert     TC.AddHIPRuntimeLibArgs(Args, CmdArgs);
2352*12c85518Srobert   } else {
2353*12c85518Srobert     // Claim "no HIP libraries" arguments if any
2354*12c85518Srobert     for (auto *Arg : Args.filtered(options::OPT_no_hip_rt)) {
2355*12c85518Srobert       Arg->claim();
2356*12c85518Srobert     }
2357*12c85518Srobert   }
2358*12c85518Srobert }
2359