xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- Gnu.cpp - Gnu Tool and ToolChain Implementations -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Gnu.h"
10 #include "Arch/ARM.h"
11 #include "Arch/CSKY.h"
12 #include "Arch/LoongArch.h"
13 #include "Arch/Mips.h"
14 #include "Arch/PPC.h"
15 #include "Arch/RISCV.h"
16 #include "Arch/Sparc.h"
17 #include "Arch/SystemZ.h"
18 #include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
19 #include "clang/Driver/CommonArgs.h"
20 #include "clang/Driver/Compilation.h"
21 #include "clang/Driver/Driver.h"
22 #include "clang/Driver/MultilibBuilder.h"
23 #include "clang/Driver/Options.h"
24 #include "clang/Driver/Tool.h"
25 #include "clang/Driver/ToolChain.h"
26 #include "llvm/ADT/StringSet.h"
27 #include "llvm/ADT/Twine.h"
28 #include "llvm/Option/ArgList.h"
29 #include "llvm/Support/CodeGen.h"
30 #include "llvm/Support/Path.h"
31 #include "llvm/Support/VirtualFileSystem.h"
32 #include "llvm/TargetParser/RISCVISAInfo.h"
33 #include "llvm/TargetParser/TargetParser.h"
34 #include <system_error>
35 
36 using namespace clang::driver;
37 using namespace clang::driver::toolchains;
38 using namespace clang;
39 using namespace llvm::opt;
40 
41 using tools::addMultilibFlag;
42 using tools::addPathIfExists;
43 
forwardToGCC(const Option & O)44 static bool forwardToGCC(const Option &O) {
45   // LinkerInput options have been forwarded. Don't duplicate.
46   if (O.hasFlag(options::LinkerInput))
47     return false;
48   return O.matches(options::OPT_Link_Group) || O.hasFlag(options::LinkOption);
49 }
50 
51 // Switch CPU names not recognized by GNU assembler to a close CPU that it does
52 // recognize, instead of a lower march from being picked in the absence of a cpu
53 // flag.
normalizeCPUNamesForAssembler(const ArgList & Args,ArgStringList & CmdArgs)54 static void normalizeCPUNamesForAssembler(const ArgList &Args,
55                                           ArgStringList &CmdArgs) {
56   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
57     StringRef CPUArg(A->getValue());
58     if (CPUArg.equals_insensitive("krait"))
59       CmdArgs.push_back("-mcpu=cortex-a15");
60     else if (CPUArg.equals_insensitive("kryo"))
61       CmdArgs.push_back("-mcpu=cortex-a57");
62     else
63       Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
64   }
65 }
66 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const67 void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
68                                       const InputInfo &Output,
69                                       const InputInfoList &Inputs,
70                                       const ArgList &Args,
71                                       const char *LinkingOutput) const {
72   const Driver &D = getToolChain().getDriver();
73   ArgStringList CmdArgs;
74 
75   for (const auto &A : Args) {
76     if (forwardToGCC(A->getOption())) {
77       // It is unfortunate that we have to claim here, as this means
78       // we will basically never report anything interesting for
79       // platforms using a generic gcc, even if we are just using gcc
80       // to get to the assembler.
81       A->claim();
82 
83       A->render(Args, CmdArgs);
84     }
85   }
86 
87   RenderExtraToolArgs(JA, CmdArgs);
88 
89   // If using a driver, force the arch.
90   if (getToolChain().getTriple().isOSDarwin()) {
91     CmdArgs.push_back("-arch");
92     CmdArgs.push_back(
93         Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
94   }
95 
96   // Try to force gcc to match the tool chain we want, if we recognize
97   // the arch.
98   //
99   // FIXME: The triple class should directly provide the information we want
100   // here.
101   switch (getToolChain().getArch()) {
102   default:
103     break;
104   case llvm::Triple::x86:
105   case llvm::Triple::ppc:
106   case llvm::Triple::ppcle:
107     CmdArgs.push_back("-m32");
108     break;
109   case llvm::Triple::x86_64:
110   case llvm::Triple::ppc64:
111   case llvm::Triple::ppc64le:
112     CmdArgs.push_back("-m64");
113     break;
114   case llvm::Triple::sparcel:
115     CmdArgs.push_back("-EL");
116     break;
117   }
118 
119   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
120   if (Output.isFilename()) {
121     CmdArgs.push_back("-o");
122     CmdArgs.push_back(Output.getFilename());
123   } else {
124     CmdArgs.push_back("-fsyntax-only");
125   }
126 
127   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
128 
129   // Only pass -x if gcc will understand it; otherwise hope gcc
130   // understands the suffix correctly. The main use case this would go
131   // wrong in is for linker inputs if they happened to have an odd
132   // suffix; really the only way to get this to happen is a command
133   // like '-x foobar a.c' which will treat a.c like a linker input.
134   //
135   // FIXME: For the linker case specifically, can we safely convert
136   // inputs into '-Wl,' options?
137   for (const auto &II : Inputs) {
138     // Don't try to pass LLVM or AST inputs to a generic gcc.
139     if (types::isLLVMIR(II.getType()))
140       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
141           << getToolChain().getTripleString();
142     else if (II.getType() == types::TY_AST)
143       D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString();
144     else if (II.getType() == types::TY_ModuleFile)
145       D.Diag(diag::err_drv_no_module_support)
146           << getToolChain().getTripleString();
147 
148     if (types::canTypeBeUserSpecified(II.getType())) {
149       CmdArgs.push_back("-x");
150       CmdArgs.push_back(types::getTypeName(II.getType()));
151     }
152 
153     if (II.isFilename())
154       CmdArgs.push_back(II.getFilename());
155     else {
156       const Arg &A = II.getInputArg();
157 
158       // Reverse translate some rewritten options.
159       if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
160         CmdArgs.push_back("-lstdc++");
161         continue;
162       }
163 
164       // Don't render as input, we need gcc to do the translations.
165       A.render(Args, CmdArgs);
166     }
167   }
168 
169   const std::string &customGCCName = D.getCCCGenericGCCName();
170   const char *GCCName;
171   if (!customGCCName.empty())
172     GCCName = customGCCName.c_str();
173   else if (D.CCCIsCXX()) {
174     GCCName = "g++";
175   } else
176     GCCName = "gcc";
177 
178   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
179   C.addCommand(std::make_unique<Command>(JA, *this,
180                                          ResponseFileSupport::AtFileCurCP(),
181                                          Exec, CmdArgs, Inputs, Output));
182 }
183 
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const184 void tools::gcc::Preprocessor::RenderExtraToolArgs(
185     const JobAction &JA, ArgStringList &CmdArgs) const {
186   CmdArgs.push_back("-E");
187 }
188 
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const189 void tools::gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,
190                                                ArgStringList &CmdArgs) const {
191   const Driver &D = getToolChain().getDriver();
192 
193   switch (JA.getType()) {
194   // If -flto, etc. are present then make sure not to force assembly output.
195   case types::TY_LLVM_IR:
196   case types::TY_LTO_IR:
197   case types::TY_LLVM_BC:
198   case types::TY_LTO_BC:
199     CmdArgs.push_back("-c");
200     break;
201   // We assume we've got an "integrated" assembler in that gcc will produce an
202   // object file itself.
203   case types::TY_Object:
204     CmdArgs.push_back("-c");
205     break;
206   case types::TY_PP_Asm:
207     CmdArgs.push_back("-S");
208     break;
209   case types::TY_Nothing:
210     CmdArgs.push_back("-fsyntax-only");
211     break;
212   default:
213     D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());
214   }
215 }
216 
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const217 void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
218                                              ArgStringList &CmdArgs) const {
219   // The types are (hopefully) good enough.
220 }
221 
getStaticPIE(const ArgList & Args,const ToolChain & TC)222 static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {
223   bool HasStaticPIE = Args.hasArg(options::OPT_static_pie);
224   if (HasStaticPIE && Args.hasArg(options::OPT_no_pie)) {
225     const Driver &D = TC.getDriver();
226     const llvm::opt::OptTable &Opts = D.getOpts();
227     StringRef StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
228     StringRef NoPIEName = Opts.getOptionName(options::OPT_nopie);
229     D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;
230   }
231   return HasStaticPIE;
232 }
233 
getStatic(const ArgList & Args)234 static bool getStatic(const ArgList &Args) {
235   return Args.hasArg(options::OPT_static) &&
236       !Args.hasArg(options::OPT_static_pie);
237 }
238 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const239 void tools::gnutools::StaticLibTool::ConstructJob(
240     Compilation &C, const JobAction &JA, const InputInfo &Output,
241     const InputInfoList &Inputs, const ArgList &Args,
242     const char *LinkingOutput) const {
243   const Driver &D = getToolChain().getDriver();
244 
245   // Silence warning for "clang -g foo.o -o foo"
246   Args.ClaimAllArgs(options::OPT_g_Group);
247   // and "clang -emit-llvm foo.o -o foo"
248   Args.ClaimAllArgs(options::OPT_emit_llvm);
249   // and for "clang -w foo.o -o foo". Other warning options are already
250   // handled somewhere else.
251   Args.ClaimAllArgs(options::OPT_w);
252   // Silence warnings when linking C code with a C++ '-stdlib' argument.
253   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
254 
255   // ar tool command "llvm-ar <options> <output_file> <input_files>".
256   ArgStringList CmdArgs;
257   // Create and insert file members with a deterministic index.
258   CmdArgs.push_back("rcsD");
259   CmdArgs.push_back(Output.getFilename());
260 
261   for (const auto &II : Inputs) {
262     if (II.isFilename()) {
263        CmdArgs.push_back(II.getFilename());
264     }
265   }
266 
267   // Delete old output archive file if it already exists before generating a new
268   // archive file.
269   auto OutputFileName = Output.getFilename();
270   if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
271     if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
272       D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
273       return;
274     }
275   }
276 
277   const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
278   C.addCommand(std::make_unique<Command>(JA, *this,
279                                          ResponseFileSupport::AtFileCurCP(),
280                                          Exec, CmdArgs, Inputs, Output));
281 }
282 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const283 void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
284                                            const InputInfo &Output,
285                                            const InputInfoList &Inputs,
286                                            const ArgList &Args,
287                                            const char *LinkingOutput) const {
288   // FIXME: The Linker class constructor takes a ToolChain and not a
289   // Generic_ELF, so the static_cast might return a reference to a invalid
290   // instance (see PR45061). Ideally, the Linker constructor needs to take a
291   // Generic_ELF instead.
292   const auto &ToolChain = static_cast<const Generic_ELF &>(getToolChain());
293   const Driver &D = ToolChain.getDriver();
294 
295   const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
296 
297   const llvm::Triple::ArchType Arch = ToolChain.getArch();
298   const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily();
299   const bool isAndroid = ToolChain.getTriple().isAndroid();
300   const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
301   const bool IsVE = ToolChain.getTriple().isVE();
302   const bool IsStaticPIE = getStaticPIE(Args, ToolChain);
303   const bool IsStatic = getStatic(Args);
304   const bool HasCRTBeginEndFiles =
305       ToolChain.getTriple().hasEnvironment() ||
306       (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);
307 
308   ArgStringList CmdArgs;
309 
310   // Silence warning for "clang -g foo.o -o foo"
311   Args.ClaimAllArgs(options::OPT_g_Group);
312   // and "clang -emit-llvm foo.o -o foo"
313   Args.ClaimAllArgs(options::OPT_emit_llvm);
314   // and for "clang -w foo.o -o foo". Other warning options are already
315   // handled somewhere else.
316   Args.ClaimAllArgs(options::OPT_w);
317 
318   if (!D.SysRoot.empty())
319     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
320 
321   if (Args.hasArg(options::OPT_s))
322     CmdArgs.push_back("-s");
323 
324   if (Triple.isARM() || Triple.isThumb()) {
325     bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
326     if (IsBigEndian)
327       arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
328     CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
329   } else if (Triple.isAArch64()) {
330     CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
331   }
332 
333   // Most Android ARM64 targets should enable the linker fix for erratum
334   // 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
335   if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily) &&
336       Args.hasFlag(options::OPT_mfix_cortex_a53_843419,
337                    options::OPT_mno_fix_cortex_a53_843419, true)) {
338     std::string CPU = getCPUName(D, Args, Triple);
339     if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
340       CmdArgs.push_back("--fix-cortex-a53-843419");
341   }
342 
343   ToolChain.addExtraOpts(CmdArgs);
344 
345   CmdArgs.push_back("--eh-frame-hdr");
346 
347   if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
348     CmdArgs.push_back("-m");
349     CmdArgs.push_back(LDMOption);
350   } else {
351     D.Diag(diag::err_target_unknown_triple) << Triple.str();
352     return;
353   }
354 
355   if (Triple.isLoongArch() || Triple.isRISCV()) {
356     CmdArgs.push_back("-X");
357     if (Args.hasArg(options::OPT_mno_relax))
358       CmdArgs.push_back("--no-relax");
359   }
360 
361   const bool IsShared = Args.hasArg(options::OPT_shared);
362   if (IsShared)
363     CmdArgs.push_back("-shared");
364   bool IsPIE = false;
365   if (IsStaticPIE) {
366     CmdArgs.push_back("-static");
367     CmdArgs.push_back("-pie");
368     CmdArgs.push_back("--no-dynamic-linker");
369     CmdArgs.push_back("-z");
370     CmdArgs.push_back("text");
371   } else if (IsStatic) {
372     CmdArgs.push_back("-static");
373   } else if (!Args.hasArg(options::OPT_r)) {
374     if (Args.hasArg(options::OPT_rdynamic))
375       CmdArgs.push_back("-export-dynamic");
376     if (!IsShared) {
377       IsPIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie,
378                            ToolChain.isPIEDefault(Args));
379       if (IsPIE)
380         CmdArgs.push_back("-pie");
381       CmdArgs.push_back("-dynamic-linker");
382       CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
383                                            ToolChain.getDynamicLinker(Args)));
384     }
385   }
386 
387   CmdArgs.push_back("-o");
388   CmdArgs.push_back(Output.getFilename());
389 
390   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
391                    options::OPT_r)) {
392     if (!isAndroid && !IsIAMCU) {
393       const char *crt1 = nullptr;
394       if (!Args.hasArg(options::OPT_shared)) {
395         if (Args.hasArg(options::OPT_pg))
396           crt1 = "gcrt1.o";
397         else if (IsPIE)
398           crt1 = "Scrt1.o";
399         else if (IsStaticPIE)
400           crt1 = "rcrt1.o";
401         else
402           crt1 = "crt1.o";
403       }
404       if (crt1)
405         CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
406 
407       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
408     }
409 
410     if (IsVE) {
411       CmdArgs.push_back("-z");
412       CmdArgs.push_back("max-page-size=0x4000000");
413     }
414 
415     if (IsIAMCU)
416       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
417     else if (HasCRTBeginEndFiles) {
418       std::string P;
419       if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&
420           !isAndroid) {
421         std::string crtbegin = ToolChain.getCompilerRT(Args, "crtbegin",
422                                                        ToolChain::FT_Object);
423         if (ToolChain.getVFS().exists(crtbegin))
424           P = crtbegin;
425       }
426       if (P.empty()) {
427         const char *crtbegin;
428         if (Args.hasArg(options::OPT_shared))
429           crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
430         else if (IsStatic)
431           crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
432         else if (IsPIE || IsStaticPIE)
433           crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
434         else
435           crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
436         P = ToolChain.GetFilePath(crtbegin);
437       }
438       CmdArgs.push_back(Args.MakeArgString(P));
439     }
440 
441     // Add crtfastmath.o if available and fast math is enabled.
442     ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
443 
444     if (isAndroid && Args.hasFlag(options::OPT_fandroid_pad_segment,
445                                   options::OPT_fno_android_pad_segment, false))
446       CmdArgs.push_back(
447           Args.MakeArgString(ToolChain.GetFilePath("crt_pad_segment.o")));
448   }
449 
450   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
451 
452   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
453 
454   if (D.isUsingLTO())
455     addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs,
456                   D.getLTOMode() == LTOK_Thin);
457 
458   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
459     CmdArgs.push_back("--no-demangle");
460 
461   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
462   bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
463   addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
464   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
465 
466   addHIPRuntimeLibArgs(ToolChain, C, Args, CmdArgs);
467 
468   // The profile runtime also needs access to system libraries.
469   getToolChain().addProfileRTLibs(Args, CmdArgs);
470 
471   if (D.CCCIsCXX() &&
472       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
473                    options::OPT_r)) {
474     if (ToolChain.ShouldLinkCXXStdlib(Args)) {
475       bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
476                                  !Args.hasArg(options::OPT_static);
477       if (OnlyLibstdcxxStatic)
478         CmdArgs.push_back("-Bstatic");
479       ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
480       if (OnlyLibstdcxxStatic)
481         CmdArgs.push_back("-Bdynamic");
482     }
483     CmdArgs.push_back("-lm");
484   }
485 
486   // Silence warnings when linking C code with a C++ '-stdlib' argument.
487   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
488 
489   // Additional linker set-up and flags for Fortran. This is required in order
490   // to generate executables. As Fortran runtime depends on the C runtime,
491   // these dependencies need to be listed before the C runtime below (i.e.
492   // AddRunTimeLibs).
493   if (D.IsFlangMode() &&
494       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
495     ToolChain.addFortranRuntimeLibraryPath(Args, CmdArgs);
496     ToolChain.addFortranRuntimeLibs(Args, CmdArgs);
497     CmdArgs.push_back("-lm");
498   }
499 
500   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
501     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
502       if (IsStatic || IsStaticPIE)
503         CmdArgs.push_back("--start-group");
504 
505       if (NeedsSanitizerDeps)
506         linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
507 
508       if (NeedsXRayDeps)
509         linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
510 
511       bool WantPthread = Args.hasArg(options::OPT_pthread) ||
512                          Args.hasArg(options::OPT_pthreads);
513 
514       // Use the static OpenMP runtime with -static-openmp
515       bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
516                           !Args.hasArg(options::OPT_static);
517 
518       // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
519       // require librt. Most modern Linux platforms do, but some may not.
520       if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP,
521                            JA.isHostOffloading(Action::OFK_OpenMP),
522                            /* GompNeedsRT= */ true))
523         // OpenMP runtimes implies pthreads when using the GNU toolchain.
524         // FIXME: Does this really make sense for all GNU toolchains?
525         WantPthread = true;
526 
527       AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
528 
529       // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
530       // forcibly link with libatomic as a workaround.
531       // TODO: Issue #41880 and D118021.
532       if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
533         CmdArgs.push_back("--push-state");
534         CmdArgs.push_back("--as-needed");
535         CmdArgs.push_back("-latomic");
536         CmdArgs.push_back("--pop-state");
537       }
538 
539       // We don't need libpthread neither for bionic (Android) nor for musl,
540       // (used by OHOS as runtime library).
541       if (WantPthread && !isAndroid && !isOHOSFamily)
542         CmdArgs.push_back("-lpthread");
543 
544       if (Args.hasArg(options::OPT_fsplit_stack))
545         CmdArgs.push_back("--wrap=pthread_create");
546 
547       if (!Args.hasArg(options::OPT_nolibc))
548         CmdArgs.push_back("-lc");
549 
550       // Add IAMCU specific libs, if needed.
551       if (IsIAMCU)
552         CmdArgs.push_back("-lgloss");
553 
554       if (IsStatic || IsStaticPIE)
555         CmdArgs.push_back("--end-group");
556       else
557         AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
558 
559       // Add IAMCU specific libs (outside the group), if needed.
560       if (IsIAMCU) {
561         CmdArgs.push_back("--as-needed");
562         CmdArgs.push_back("-lsoftfp");
563         CmdArgs.push_back("--no-as-needed");
564       }
565     }
566 
567     if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) {
568       if (HasCRTBeginEndFiles) {
569         std::string P;
570         if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&
571             !isAndroid) {
572           std::string crtend = ToolChain.getCompilerRT(Args, "crtend",
573                                                        ToolChain::FT_Object);
574           if (ToolChain.getVFS().exists(crtend))
575             P = crtend;
576         }
577         if (P.empty()) {
578           const char *crtend;
579           if (Args.hasArg(options::OPT_shared))
580             crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
581           else if (IsPIE || IsStaticPIE)
582             crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
583           else
584             crtend = isAndroid ? "crtend_android.o" : "crtend.o";
585           P = ToolChain.GetFilePath(crtend);
586         }
587         CmdArgs.push_back(Args.MakeArgString(P));
588       }
589       if (!isAndroid)
590         CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
591     }
592   }
593 
594   Args.addAllArgs(CmdArgs, {options::OPT_T, options::OPT_t});
595 
596   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
597   C.addCommand(std::make_unique<Command>(JA, *this,
598                                          ResponseFileSupport::AtFileCurCP(),
599                                          Exec, CmdArgs, Inputs, Output));
600 }
601 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const602 void tools::gnutools::Assembler::ConstructJob(Compilation &C,
603                                               const JobAction &JA,
604                                               const InputInfo &Output,
605                                               const InputInfoList &Inputs,
606                                               const ArgList &Args,
607                                               const char *LinkingOutput) const {
608   const auto &D = getToolChain().getDriver();
609 
610   claimNoWarnArgs(Args);
611 
612   ArgStringList CmdArgs;
613 
614   llvm::Reloc::Model RelocationModel;
615   unsigned PICLevel;
616   bool IsPIE;
617   const char *DefaultAssembler = "as";
618   // Enforce GNU as on Solaris; the native assembler's input syntax isn't fully
619   // compatible.
620   if (getToolChain().getTriple().isOSSolaris())
621     DefaultAssembler = "gas";
622   std::tie(RelocationModel, PICLevel, IsPIE) =
623       ParsePICArgs(getToolChain(), Args);
624 
625   if (const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ)) {
626     if (A->getOption().getID() == options::OPT_gz) {
627       CmdArgs.push_back("--compress-debug-sections");
628     } else {
629       StringRef Value = A->getValue();
630       if (Value == "none" || Value == "zlib" || Value == "zstd") {
631         CmdArgs.push_back(
632             Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
633       } else {
634         D.Diag(diag::err_drv_unsupported_option_argument)
635             << A->getSpelling() << Value;
636       }
637     }
638   }
639 
640   switch (getToolChain().getArch()) {
641   default:
642     break;
643   // Add --32/--64 to make sure we get the format we want.
644   // This is incomplete
645   case llvm::Triple::x86:
646     CmdArgs.push_back("--32");
647     break;
648   case llvm::Triple::x86_64:
649     if (getToolChain().getTriple().isX32())
650       CmdArgs.push_back("--x32");
651     else
652       CmdArgs.push_back("--64");
653     break;
654   case llvm::Triple::ppc: {
655     CmdArgs.push_back("-a32");
656     CmdArgs.push_back("-mppc");
657     CmdArgs.push_back("-mbig-endian");
658     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
659         getCPUName(D, Args, getToolChain().getTriple())));
660     break;
661   }
662   case llvm::Triple::ppcle: {
663     CmdArgs.push_back("-a32");
664     CmdArgs.push_back("-mppc");
665     CmdArgs.push_back("-mlittle-endian");
666     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
667         getCPUName(D, Args, getToolChain().getTriple())));
668     break;
669   }
670   case llvm::Triple::ppc64: {
671     CmdArgs.push_back("-a64");
672     CmdArgs.push_back("-mppc64");
673     CmdArgs.push_back("-mbig-endian");
674     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
675         getCPUName(D, Args, getToolChain().getTriple())));
676     break;
677   }
678   case llvm::Triple::ppc64le: {
679     CmdArgs.push_back("-a64");
680     CmdArgs.push_back("-mppc64");
681     CmdArgs.push_back("-mlittle-endian");
682     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
683         getCPUName(D, Args, getToolChain().getTriple())));
684     break;
685   }
686   case llvm::Triple::riscv32:
687   case llvm::Triple::riscv64: {
688     StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
689     CmdArgs.push_back("-mabi");
690     CmdArgs.push_back(ABIName.data());
691     std::string MArchName =
692         riscv::getRISCVArch(Args, getToolChain().getTriple());
693     CmdArgs.push_back("-march");
694     CmdArgs.push_back(Args.MakeArgString(MArchName));
695     if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
696       Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);
697     break;
698   }
699   case llvm::Triple::sparc:
700   case llvm::Triple::sparcel: {
701     CmdArgs.push_back("-32");
702     std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
703     CmdArgs.push_back(
704         sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
705     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
706     break;
707   }
708   case llvm::Triple::sparcv9: {
709     CmdArgs.push_back("-64");
710     std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
711     CmdArgs.push_back(
712         sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
713     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
714     break;
715   }
716   case llvm::Triple::arm:
717   case llvm::Triple::armeb:
718   case llvm::Triple::thumb:
719   case llvm::Triple::thumbeb: {
720     const llvm::Triple &Triple2 = getToolChain().getTriple();
721     CmdArgs.push_back(arm::isARMBigEndian(Triple2, Args) ? "-EB" : "-EL");
722     switch (Triple2.getSubArch()) {
723     case llvm::Triple::ARMSubArch_v7:
724       CmdArgs.push_back("-mfpu=neon");
725       break;
726     case llvm::Triple::ARMSubArch_v8:
727       CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
728       break;
729     default:
730       break;
731     }
732 
733     switch (arm::getARMFloatABI(getToolChain(), Args)) {
734     case arm::FloatABI::Invalid: llvm_unreachable("must have an ABI!");
735     case arm::FloatABI::Soft:
736       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=soft"));
737       break;
738     case arm::FloatABI::SoftFP:
739       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=softfp"));
740       break;
741     case arm::FloatABI::Hard:
742       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=hard"));
743       break;
744     }
745 
746     Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
747     normalizeCPUNamesForAssembler(Args, CmdArgs);
748 
749     Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
750     // The integrated assembler doesn't implement e_flags setting behavior for
751     // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For
752     // compatibility we accept but warn.
753     if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
754       A->ignoreTargetSpecific();
755     break;
756   }
757   case llvm::Triple::aarch64:
758   case llvm::Triple::aarch64_be: {
759     CmdArgs.push_back(
760         getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL");
761     Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
762     normalizeCPUNamesForAssembler(Args, CmdArgs);
763 
764     break;
765   }
766   // TODO: handle loongarch32.
767   case llvm::Triple::loongarch64: {
768     StringRef ABIName =
769         loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());
770     CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));
771     break;
772   }
773   case llvm::Triple::mips:
774   case llvm::Triple::mipsel:
775   case llvm::Triple::mips64:
776   case llvm::Triple::mips64el: {
777     StringRef CPUName;
778     StringRef ABIName;
779     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
780     ABIName = mips::getGnuCompatibleMipsABIName(ABIName);
781 
782     CmdArgs.push_back("-march");
783     CmdArgs.push_back(CPUName.data());
784 
785     CmdArgs.push_back("-mabi");
786     CmdArgs.push_back(ABIName.data());
787 
788     // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
789     // or -mshared (not implemented) is in effect.
790     if (RelocationModel == llvm::Reloc::Static)
791       CmdArgs.push_back("-mno-shared");
792 
793     // LLVM doesn't support -mplt yet and acts as if it is always given.
794     // However, -mplt has no effect with the N64 ABI.
795     if (ABIName != "64" && !Args.hasArg(options::OPT_mno_abicalls))
796       CmdArgs.push_back("-call_nonpic");
797 
798     if (getToolChain().getTriple().isLittleEndian())
799       CmdArgs.push_back("-EL");
800     else
801       CmdArgs.push_back("-EB");
802 
803     if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
804       if (StringRef(A->getValue()) == "2008")
805         CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
806     }
807 
808     // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
809     if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
810                                  options::OPT_mfp64)) {
811       A->claim();
812       A->render(Args, CmdArgs);
813     } else if (mips::shouldUseFPXX(
814                    Args, getToolChain().getTriple(), CPUName, ABIName,
815                    mips::getMipsFloatABI(getToolChain().getDriver(), Args,
816                                          getToolChain().getTriple())))
817       CmdArgs.push_back("-mfpxx");
818 
819     // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
820     // -mno-mips16 is actually -no-mips16.
821     if (Arg *A =
822             Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16)) {
823       if (A->getOption().matches(options::OPT_mips16)) {
824         A->claim();
825         A->render(Args, CmdArgs);
826       } else {
827         A->claim();
828         CmdArgs.push_back("-no-mips16");
829       }
830     }
831 
832     Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
833                     options::OPT_mno_micromips);
834     Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
835     Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);
836 
837     if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
838       // Do not use AddLastArg because not all versions of MIPS assembler
839       // support -mmsa / -mno-msa options.
840       if (A->getOption().matches(options::OPT_mmsa))
841         CmdArgs.push_back(Args.MakeArgString("-mmsa"));
842     }
843 
844     Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
845                     options::OPT_msoft_float);
846 
847     Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,
848                     options::OPT_msingle_float);
849 
850     Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
851                     options::OPT_mno_odd_spreg);
852 
853     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
854     break;
855   }
856   case llvm::Triple::systemz: {
857     // Always pass an -march option, since our default of z10 is later
858     // than the GNU assembler's default.
859     std::string CPUName =
860         systemz::getSystemZTargetCPU(Args, getToolChain().getTriple());
861     CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
862     break;
863   }
864   case llvm::Triple::ve:
865     DefaultAssembler = "nas";
866   }
867 
868   for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
869                                     options::OPT_fdebug_prefix_map_EQ)) {
870     StringRef Map = A->getValue();
871     if (!Map.contains('='))
872       D.Diag(diag::err_drv_invalid_argument_to_option)
873           << Map << A->getOption().getName();
874     else {
875       CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));
876       CmdArgs.push_back(Args.MakeArgString(Map));
877     }
878     A->claim();
879   }
880 
881   Args.AddAllArgs(CmdArgs, options::OPT_I);
882   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
883 
884   CmdArgs.push_back("-o");
885   CmdArgs.push_back(Output.getFilename());
886 
887   for (const auto &II : Inputs)
888     CmdArgs.push_back(II.getFilename());
889 
890   if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group,
891                                options::OPT_gdwarf_2, options::OPT_gdwarf_3,
892                                options::OPT_gdwarf_4, options::OPT_gdwarf_5,
893                                options::OPT_gdwarf))
894     if (!A->getOption().matches(options::OPT_g0)) {
895       Args.AddLastArg(CmdArgs, options::OPT_g_Flag);
896 
897       unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
898       CmdArgs.push_back(Args.MakeArgString("-gdwarf-" + Twine(DwarfVersion)));
899     }
900 
901   const char *Exec =
902       Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));
903   C.addCommand(std::make_unique<Command>(JA, *this,
904                                          ResponseFileSupport::AtFileCurCP(),
905                                          Exec, CmdArgs, Inputs, Output));
906 
907   // Handle the debug info splitting at object creation time if we're
908   // creating an object.
909   // TODO: Currently only works on linux with newer objcopy.
910   if (Args.hasArg(options::OPT_gsplit_dwarf) &&
911       getToolChain().getTriple().isOSLinux())
912     SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
913                    SplitDebugName(JA, Args, Inputs[0], Output));
914 }
915 
916 namespace {
917 // Filter to remove Multilibs that don't exist as a suffix to Path
918 class FilterNonExistent {
919   StringRef Base, File;
920   llvm::vfs::FileSystem &VFS;
921 
922 public:
FilterNonExistent(StringRef Base,StringRef File,llvm::vfs::FileSystem & VFS)923   FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)
924       : Base(Base), File(File), VFS(VFS) {}
operator ()(const Multilib & M)925   bool operator()(const Multilib &M) {
926     return !VFS.exists(Base + M.gccSuffix() + File);
927   }
928 };
929 } // end anonymous namespace
930 
isSoftFloatABI(const ArgList & Args)931 static bool isSoftFloatABI(const ArgList &Args) {
932   Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
933                            options::OPT_mfloat_abi_EQ);
934   if (!A)
935     return false;
936 
937   return A->getOption().matches(options::OPT_msoft_float) ||
938          (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
939           A->getValue() == StringRef("soft"));
940 }
941 
isArmOrThumbArch(llvm::Triple::ArchType Arch)942 static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {
943   return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;
944 }
945 
isMipsEL(llvm::Triple::ArchType Arch)946 static bool isMipsEL(llvm::Triple::ArchType Arch) {
947   return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
948 }
949 
isMips16(const ArgList & Args)950 static bool isMips16(const ArgList &Args) {
951   Arg *A = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
952   return A && A->getOption().matches(options::OPT_mips16);
953 }
954 
isMicroMips(const ArgList & Args)955 static bool isMicroMips(const ArgList &Args) {
956   Arg *A = Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
957   return A && A->getOption().matches(options::OPT_mmicromips);
958 }
959 
isMSP430(llvm::Triple::ArchType Arch)960 static bool isMSP430(llvm::Triple::ArchType Arch) {
961   return Arch == llvm::Triple::msp430;
962 }
963 
findMipsCsMultilibs(const Driver & D,const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)964 static bool findMipsCsMultilibs(const Driver &D,
965                                 const Multilib::flags_list &Flags,
966                                 FilterNonExistent &NonExistent,
967                                 DetectedMultilibs &Result) {
968   // Check for Code Sourcery toolchain multilibs
969   MultilibSet CSMipsMultilibs;
970   {
971     auto MArchMips16 = MultilibBuilder("/mips16").flag("-m32").flag("-mips16");
972 
973     auto MArchMicroMips =
974         MultilibBuilder("/micromips").flag("-m32").flag("-mmicromips");
975 
976     auto MArchDefault = MultilibBuilder("")
977                             .flag("-mips16", /*Disallow=*/true)
978                             .flag("-mmicromips", /*Disallow=*/true);
979 
980     auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
981 
982     auto SoftFloat = MultilibBuilder("/soft-float").flag("-msoft-float");
983 
984     auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
985 
986     auto DefaultFloat = MultilibBuilder("")
987                             .flag("-msoft-float", /*Disallow=*/true)
988                             .flag("-mnan=2008", /*Disallow=*/true);
989 
990     auto BigEndian =
991         MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
992 
993     auto LittleEndian =
994         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
995 
996     // Note that this one's osSuffix is ""
997     auto MAbi64 = MultilibBuilder("")
998                       .gccSuffix("/64")
999                       .includeSuffix("/64")
1000                       .flag("-mabi=n64")
1001                       .flag("-mabi=n32", /*Disallow=*/true)
1002                       .flag("-m32", /*Disallow=*/true);
1003 
1004     CSMipsMultilibs =
1005         MultilibSetBuilder()
1006             .Either(MArchMips16, MArchMicroMips, MArchDefault)
1007             .Maybe(UCLibc)
1008             .Either(SoftFloat, Nan2008, DefaultFloat)
1009             .FilterOut("/micromips/nan2008")
1010             .FilterOut("/mips16/nan2008")
1011             .Either(BigEndian, LittleEndian)
1012             .Maybe(MAbi64)
1013             .FilterOut("/mips16.*/64")
1014             .FilterOut("/micromips.*/64")
1015             .makeMultilibSet()
1016             .FilterOut(NonExistent)
1017             .setIncludeDirsCallback([](const Multilib &M) {
1018               std::vector<std::string> Dirs({"/include"});
1019               if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
1020                 Dirs.push_back(
1021                     "/../../../../mips-linux-gnu/libc/uclibc/usr/include");
1022               else
1023                 Dirs.push_back("/../../../../mips-linux-gnu/libc/usr/include");
1024               return Dirs;
1025             });
1026   }
1027 
1028   MultilibSet DebianMipsMultilibs;
1029   {
1030     MultilibBuilder MAbiN32 =
1031         MultilibBuilder().gccSuffix("/n32").includeSuffix("/n32").flag(
1032             "-mabi=n32");
1033 
1034     MultilibBuilder M64 = MultilibBuilder()
1035                               .gccSuffix("/64")
1036                               .includeSuffix("/64")
1037                               .flag("-m64")
1038                               .flag("-m32", /*Disallow=*/true)
1039                               .flag("-mabi=n32", /*Disallow=*/true);
1040 
1041     MultilibBuilder M32 = MultilibBuilder()
1042                               .gccSuffix("/32")
1043                               .flag("-m64", /*Disallow=*/true)
1044                               .flag("-m32")
1045                               .flag("-mabi=n32", /*Disallow=*/true);
1046 
1047     DebianMipsMultilibs = MultilibSetBuilder()
1048                               .Either(M32, M64, MAbiN32)
1049                               .makeMultilibSet()
1050                               .FilterOut(NonExistent);
1051   }
1052 
1053   // Sort candidates. Toolchain that best meets the directories tree goes first.
1054   // Then select the first toolchains matches command line flags.
1055   MultilibSet *Candidates[] = {&CSMipsMultilibs, &DebianMipsMultilibs};
1056   if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())
1057     std::iter_swap(Candidates, Candidates + 1);
1058   for (const MultilibSet *Candidate : Candidates) {
1059     if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
1060       if (Candidate == &DebianMipsMultilibs)
1061         Result.BiarchSibling = Multilib();
1062       Result.Multilibs = *Candidate;
1063       return true;
1064     }
1065   }
1066   return false;
1067 }
1068 
findMipsMuslMultilibs(const Driver & D,const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)1069 static bool findMipsMuslMultilibs(const Driver &D,
1070                                   const Multilib::flags_list &Flags,
1071                                   FilterNonExistent &NonExistent,
1072                                   DetectedMultilibs &Result) {
1073   // Musl toolchain multilibs
1074   MultilibSet MuslMipsMultilibs;
1075   {
1076     auto MArchMipsR2 = MultilibBuilder("")
1077                            .osSuffix("/mips-r2-hard-musl")
1078                            .flag("-EB")
1079                            .flag("-EL", /*Disallow=*/true)
1080                            .flag("-march=mips32r2");
1081 
1082     auto MArchMipselR2 = MultilibBuilder("/mipsel-r2-hard-musl")
1083                              .flag("-EB", /*Disallow=*/true)
1084                              .flag("-EL")
1085                              .flag("-march=mips32r2");
1086 
1087     MuslMipsMultilibs = MultilibSetBuilder()
1088                             .Either(MArchMipsR2, MArchMipselR2)
1089                             .makeMultilibSet();
1090 
1091     // Specify the callback that computes the include directories.
1092     MuslMipsMultilibs.setIncludeDirsCallback([](const Multilib &M) {
1093       return std::vector<std::string>(
1094           {"/../sysroot" + M.osSuffix() + "/usr/include"});
1095     });
1096   }
1097   if (MuslMipsMultilibs.select(D, Flags, Result.SelectedMultilibs)) {
1098     Result.Multilibs = MuslMipsMultilibs;
1099     return true;
1100   }
1101   return false;
1102 }
1103 
findMipsMtiMultilibs(const Driver & D,const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)1104 static bool findMipsMtiMultilibs(const Driver &D,
1105                                  const Multilib::flags_list &Flags,
1106                                  FilterNonExistent &NonExistent,
1107                                  DetectedMultilibs &Result) {
1108   // CodeScape MTI toolchain v1.2 and early.
1109   MultilibSet MtiMipsMultilibsV1;
1110   {
1111     auto MArchMips32 = MultilibBuilder("/mips32")
1112                            .flag("-m32")
1113                            .flag("-m64", /*Disallow=*/true)
1114                            .flag("-mmicromips", /*Disallow=*/true)
1115                            .flag("-march=mips32");
1116 
1117     auto MArchMicroMips = MultilibBuilder("/micromips")
1118                               .flag("-m32")
1119                               .flag("-m64", /*Disallow=*/true)
1120                               .flag("-mmicromips");
1121 
1122     auto MArchMips64r2 = MultilibBuilder("/mips64r2")
1123                              .flag("-m32", /*Disallow=*/true)
1124                              .flag("-m64")
1125                              .flag("-march=mips64r2");
1126 
1127     auto MArchMips64 = MultilibBuilder("/mips64")
1128                            .flag("-m32", /*Disallow=*/true)
1129                            .flag("-m64")
1130                            .flag("-march=mips64r2", /*Disallow=*/true);
1131 
1132     auto MArchDefault = MultilibBuilder("")
1133                             .flag("-m32")
1134                             .flag("-m64", /*Disallow=*/true)
1135                             .flag("-mmicromips", /*Disallow=*/true)
1136                             .flag("-march=mips32r2");
1137 
1138     auto Mips16 = MultilibBuilder("/mips16").flag("-mips16");
1139 
1140     auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
1141 
1142     auto MAbi64 = MultilibBuilder("/64")
1143                       .flag("-mabi=n64")
1144                       .flag("-mabi=n32", /*Disallow=*/true)
1145                       .flag("-m32", /*Disallow=*/true);
1146 
1147     auto BigEndian =
1148         MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
1149 
1150     auto LittleEndian =
1151         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
1152 
1153     auto SoftFloat = MultilibBuilder("/sof").flag("-msoft-float");
1154 
1155     auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
1156 
1157     MtiMipsMultilibsV1 =
1158         MultilibSetBuilder()
1159             .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64,
1160                     MArchDefault)
1161             .Maybe(UCLibc)
1162             .Maybe(Mips16)
1163             .FilterOut("/mips64/mips16")
1164             .FilterOut("/mips64r2/mips16")
1165             .FilterOut("/micromips/mips16")
1166             .Maybe(MAbi64)
1167             .FilterOut("/micromips/64")
1168             .FilterOut("/mips32/64")
1169             .FilterOut("^/64")
1170             .FilterOut("/mips16/64")
1171             .Either(BigEndian, LittleEndian)
1172             .Maybe(SoftFloat)
1173             .Maybe(Nan2008)
1174             .FilterOut(".*sof/nan2008")
1175             .makeMultilibSet()
1176             .FilterOut(NonExistent)
1177             .setIncludeDirsCallback([](const Multilib &M) {
1178               std::vector<std::string> Dirs({"/include"});
1179               if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
1180                 Dirs.push_back("/../../../../sysroot/uclibc/usr/include");
1181               else
1182                 Dirs.push_back("/../../../../sysroot/usr/include");
1183               return Dirs;
1184             });
1185   }
1186 
1187   // CodeScape IMG toolchain starting from v1.3.
1188   MultilibSet MtiMipsMultilibsV2;
1189   {
1190     auto BeHard = MultilibBuilder("/mips-r2-hard")
1191                       .flag("-EB")
1192                       .flag("-msoft-float", /*Disallow=*/true)
1193                       .flag("-mnan=2008", /*Disallow=*/true)
1194                       .flag("-muclibc", /*Disallow=*/true);
1195     auto BeSoft = MultilibBuilder("/mips-r2-soft")
1196                       .flag("-EB")
1197                       .flag("-msoft-float")
1198                       .flag("-mnan=2008", /*Disallow=*/true);
1199     auto ElHard = MultilibBuilder("/mipsel-r2-hard")
1200                       .flag("-EL")
1201                       .flag("-msoft-float", /*Disallow=*/true)
1202                       .flag("-mnan=2008", /*Disallow=*/true)
1203                       .flag("-muclibc", /*Disallow=*/true);
1204     auto ElSoft = MultilibBuilder("/mipsel-r2-soft")
1205                       .flag("-EL")
1206                       .flag("-msoft-float")
1207                       .flag("-mnan=2008", /*Disallow=*/true)
1208                       .flag("-mmicromips", /*Disallow=*/true);
1209     auto BeHardNan = MultilibBuilder("/mips-r2-hard-nan2008")
1210                          .flag("-EB")
1211                          .flag("-msoft-float", /*Disallow=*/true)
1212                          .flag("-mnan=2008")
1213                          .flag("-muclibc", /*Disallow=*/true);
1214     auto ElHardNan = MultilibBuilder("/mipsel-r2-hard-nan2008")
1215                          .flag("-EL")
1216                          .flag("-msoft-float", /*Disallow=*/true)
1217                          .flag("-mnan=2008")
1218                          .flag("-muclibc", /*Disallow=*/true)
1219                          .flag("-mmicromips", /*Disallow=*/true);
1220     auto BeHardNanUclibc = MultilibBuilder("/mips-r2-hard-nan2008-uclibc")
1221                                .flag("-EB")
1222                                .flag("-msoft-float", /*Disallow=*/true)
1223                                .flag("-mnan=2008")
1224                                .flag("-muclibc");
1225     auto ElHardNanUclibc = MultilibBuilder("/mipsel-r2-hard-nan2008-uclibc")
1226                                .flag("-EL")
1227                                .flag("-msoft-float", /*Disallow=*/true)
1228                                .flag("-mnan=2008")
1229                                .flag("-muclibc");
1230     auto BeHardUclibc = MultilibBuilder("/mips-r2-hard-uclibc")
1231                             .flag("-EB")
1232                             .flag("-msoft-float", /*Disallow=*/true)
1233                             .flag("-mnan=2008", /*Disallow=*/true)
1234                             .flag("-muclibc");
1235     auto ElHardUclibc = MultilibBuilder("/mipsel-r2-hard-uclibc")
1236                             .flag("-EL")
1237                             .flag("-msoft-float", /*Disallow=*/true)
1238                             .flag("-mnan=2008", /*Disallow=*/true)
1239                             .flag("-muclibc");
1240     auto ElMicroHardNan = MultilibBuilder("/micromipsel-r2-hard-nan2008")
1241                               .flag("-EL")
1242                               .flag("-msoft-float", /*Disallow=*/true)
1243                               .flag("-mnan=2008")
1244                               .flag("-mmicromips");
1245     auto ElMicroSoft = MultilibBuilder("/micromipsel-r2-soft")
1246                            .flag("-EL")
1247                            .flag("-msoft-float")
1248                            .flag("-mnan=2008", /*Disallow=*/true)
1249                            .flag("-mmicromips");
1250 
1251     auto O32 = MultilibBuilder("/lib")
1252                    .osSuffix("")
1253                    .flag("-mabi=n32", /*Disallow=*/true)
1254                    .flag("-mabi=n64", /*Disallow=*/true);
1255     auto N32 = MultilibBuilder("/lib32")
1256                    .osSuffix("")
1257                    .flag("-mabi=n32")
1258                    .flag("-mabi=n64", /*Disallow=*/true);
1259     auto N64 = MultilibBuilder("/lib64")
1260                    .osSuffix("")
1261                    .flag("-mabi=n32", /*Disallow=*/true)
1262                    .flag("-mabi=n64");
1263 
1264     MtiMipsMultilibsV2 =
1265         MultilibSetBuilder()
1266             .Either({BeHard, BeSoft, ElHard, ElSoft, BeHardNan, ElHardNan,
1267                      BeHardNanUclibc, ElHardNanUclibc, BeHardUclibc,
1268                      ElHardUclibc, ElMicroHardNan, ElMicroSoft})
1269             .Either(O32, N32, N64)
1270             .makeMultilibSet()
1271             .FilterOut(NonExistent)
1272             .setIncludeDirsCallback([](const Multilib &M) {
1273               return std::vector<std::string>({"/../../../../sysroot" +
1274                                                M.includeSuffix() +
1275                                                "/../usr/include"});
1276             })
1277             .setFilePathsCallback([](const Multilib &M) {
1278               return std::vector<std::string>(
1279                   {"/../../../../mips-mti-linux-gnu/lib" + M.gccSuffix()});
1280             });
1281   }
1282   for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
1283     if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
1284       Result.Multilibs = *Candidate;
1285       return true;
1286     }
1287   }
1288   return false;
1289 }
1290 
findMipsImgMultilibs(const Driver & D,const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)1291 static bool findMipsImgMultilibs(const Driver &D,
1292                                  const Multilib::flags_list &Flags,
1293                                  FilterNonExistent &NonExistent,
1294                                  DetectedMultilibs &Result) {
1295   // CodeScape IMG toolchain v1.2 and early.
1296   MultilibSet ImgMultilibsV1;
1297   {
1298     auto Mips64r6 = MultilibBuilder("/mips64r6")
1299                         .flag("-m64")
1300                         .flag("-m32", /*Disallow=*/true);
1301 
1302     auto LittleEndian =
1303         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
1304 
1305     auto MAbi64 = MultilibBuilder("/64")
1306                       .flag("-mabi=n64")
1307                       .flag("-mabi=n32", /*Disallow=*/true)
1308                       .flag("-m32", /*Disallow=*/true);
1309 
1310     ImgMultilibsV1 =
1311         MultilibSetBuilder()
1312             .Maybe(Mips64r6)
1313             .Maybe(MAbi64)
1314             .Maybe(LittleEndian)
1315             .makeMultilibSet()
1316             .FilterOut(NonExistent)
1317             .setIncludeDirsCallback([](const Multilib &M) {
1318               return std::vector<std::string>(
1319                   {"/include", "/../../../../sysroot/usr/include"});
1320             });
1321   }
1322 
1323   // CodeScape IMG toolchain starting from v1.3.
1324   MultilibSet ImgMultilibsV2;
1325   {
1326     auto BeHard = MultilibBuilder("/mips-r6-hard")
1327                       .flag("-EB")
1328                       .flag("-msoft-float", /*Disallow=*/true)
1329                       .flag("-mmicromips", /*Disallow=*/true);
1330     auto BeSoft = MultilibBuilder("/mips-r6-soft")
1331                       .flag("-EB")
1332                       .flag("-msoft-float")
1333                       .flag("-mmicromips", /*Disallow=*/true);
1334     auto ElHard = MultilibBuilder("/mipsel-r6-hard")
1335                       .flag("-EL")
1336                       .flag("-msoft-float", /*Disallow=*/true)
1337                       .flag("-mmicromips", /*Disallow=*/true);
1338     auto ElSoft = MultilibBuilder("/mipsel-r6-soft")
1339                       .flag("-EL")
1340                       .flag("-msoft-float")
1341                       .flag("-mmicromips", /*Disallow=*/true);
1342     auto BeMicroHard = MultilibBuilder("/micromips-r6-hard")
1343                            .flag("-EB")
1344                            .flag("-msoft-float", /*Disallow=*/true)
1345                            .flag("-mmicromips");
1346     auto BeMicroSoft = MultilibBuilder("/micromips-r6-soft")
1347                            .flag("-EB")
1348                            .flag("-msoft-float")
1349                            .flag("-mmicromips");
1350     auto ElMicroHard = MultilibBuilder("/micromipsel-r6-hard")
1351                            .flag("-EL")
1352                            .flag("-msoft-float", /*Disallow=*/true)
1353                            .flag("-mmicromips");
1354     auto ElMicroSoft = MultilibBuilder("/micromipsel-r6-soft")
1355                            .flag("-EL")
1356                            .flag("-msoft-float")
1357                            .flag("-mmicromips");
1358 
1359     auto O32 = MultilibBuilder("/lib")
1360                    .osSuffix("")
1361                    .flag("-mabi=n32", /*Disallow=*/true)
1362                    .flag("-mabi=n64", /*Disallow=*/true);
1363     auto N32 = MultilibBuilder("/lib32")
1364                    .osSuffix("")
1365                    .flag("-mabi=n32")
1366                    .flag("-mabi=n64", /*Disallow=*/true);
1367     auto N64 = MultilibBuilder("/lib64")
1368                    .osSuffix("")
1369                    .flag("-mabi=n32", /*Disallow=*/true)
1370                    .flag("-mabi=n64");
1371 
1372     ImgMultilibsV2 =
1373         MultilibSetBuilder()
1374             .Either({BeHard, BeSoft, ElHard, ElSoft, BeMicroHard, BeMicroSoft,
1375                      ElMicroHard, ElMicroSoft})
1376             .Either(O32, N32, N64)
1377             .makeMultilibSet()
1378             .FilterOut(NonExistent)
1379             .setIncludeDirsCallback([](const Multilib &M) {
1380               return std::vector<std::string>({"/../../../../sysroot" +
1381                                                M.includeSuffix() +
1382                                                "/../usr/include"});
1383             })
1384             .setFilePathsCallback([](const Multilib &M) {
1385               return std::vector<std::string>(
1386                   {"/../../../../mips-img-linux-gnu/lib" + M.gccSuffix()});
1387             });
1388   }
1389   for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
1390     if (Candidate->select(D, Flags, Result.SelectedMultilibs)) {
1391       Result.Multilibs = *Candidate;
1392       return true;
1393     }
1394   }
1395   return false;
1396 }
1397 
findMIPSMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1398 bool clang::driver::findMIPSMultilibs(const Driver &D,
1399                                       const llvm::Triple &TargetTriple,
1400                                       StringRef Path, const ArgList &Args,
1401                                       DetectedMultilibs &Result) {
1402   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1403 
1404   StringRef CPUName;
1405   StringRef ABIName;
1406   tools::mips::getMipsCPUAndABI(Args, TargetTriple, CPUName, ABIName);
1407 
1408   llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
1409 
1410   Multilib::flags_list Flags;
1411   addMultilibFlag(TargetTriple.isMIPS32(), "-m32", Flags);
1412   addMultilibFlag(TargetTriple.isMIPS64(), "-m64", Flags);
1413   addMultilibFlag(isMips16(Args), "-mips16", Flags);
1414   addMultilibFlag(CPUName == "mips32", "-march=mips32", Flags);
1415   addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
1416                       CPUName == "mips32r5" || CPUName == "p5600",
1417                   "-march=mips32r2", Flags);
1418   addMultilibFlag(CPUName == "mips32r6", "-march=mips32r6", Flags);
1419   addMultilibFlag(CPUName == "mips64", "-march=mips64", Flags);
1420   addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
1421                       CPUName == "mips64r5" || CPUName == "octeon" ||
1422                       CPUName == "octeon+",
1423                   "-march=mips64r2", Flags);
1424   addMultilibFlag(CPUName == "mips64r6" || CPUName == "i6400" ||
1425                       CPUName == "i6500",
1426                   "-march=mips64r6", Flags);
1427   addMultilibFlag(isMicroMips(Args), "-mmicromips", Flags);
1428   addMultilibFlag(tools::mips::isUCLibc(Args), "-muclibc", Flags);
1429   addMultilibFlag(tools::mips::isNaN2008(D, Args, TargetTriple), "-mnan=2008",
1430                   Flags);
1431   addMultilibFlag(ABIName == "n32", "-mabi=n32", Flags);
1432   addMultilibFlag(ABIName == "n64", "-mabi=n64", Flags);
1433   addMultilibFlag(isSoftFloatABI(Args), "-msoft-float", Flags);
1434   addMultilibFlag(!isSoftFloatABI(Args), "-mhard-float", Flags);
1435   addMultilibFlag(isMipsEL(TargetArch), "-EL", Flags);
1436   addMultilibFlag(!isMipsEL(TargetArch), "-EB", Flags);
1437 
1438   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
1439       TargetTriple.getOS() == llvm::Triple::Linux &&
1440       TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
1441     return findMipsMuslMultilibs(D, Flags, NonExistent, Result);
1442 
1443   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
1444       TargetTriple.getOS() == llvm::Triple::Linux &&
1445       TargetTriple.isGNUEnvironment())
1446     return findMipsMtiMultilibs(D, Flags, NonExistent, Result);
1447 
1448   if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
1449       TargetTriple.getOS() == llvm::Triple::Linux &&
1450       TargetTriple.isGNUEnvironment())
1451     return findMipsImgMultilibs(D, Flags, NonExistent, Result);
1452 
1453   if (findMipsCsMultilibs(D, Flags, NonExistent, Result))
1454     return true;
1455 
1456   // Fallback to the regular toolchain-tree structure.
1457   Multilib Default;
1458   Result.Multilibs.push_back(Default);
1459   Result.Multilibs.FilterOut(NonExistent);
1460 
1461   if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs)) {
1462     Result.BiarchSibling = Multilib();
1463     return true;
1464   }
1465 
1466   return false;
1467 }
1468 
findAndroidArmMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1469 static void findAndroidArmMultilibs(const Driver &D,
1470                                     const llvm::Triple &TargetTriple,
1471                                     StringRef Path, const ArgList &Args,
1472                                     DetectedMultilibs &Result) {
1473   // Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb.
1474   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1475   MultilibBuilder ArmV7Multilib = MultilibBuilder("/armv7-a")
1476                                       .flag("-march=armv7-a")
1477                                       .flag("-mthumb", /*Disallow=*/true);
1478   MultilibBuilder ThumbMultilib = MultilibBuilder("/thumb")
1479                                       .flag("-march=armv7-a", /*Disallow=*/true)
1480                                       .flag("-mthumb");
1481   MultilibBuilder ArmV7ThumbMultilib =
1482       MultilibBuilder("/armv7-a/thumb").flag("-march=armv7-a").flag("-mthumb");
1483   MultilibBuilder DefaultMultilib =
1484       MultilibBuilder("")
1485           .flag("-march=armv7-a", /*Disallow=*/true)
1486           .flag("-mthumb", /*Disallow=*/true);
1487   MultilibSet AndroidArmMultilibs =
1488       MultilibSetBuilder()
1489           .Either(ThumbMultilib, ArmV7Multilib, ArmV7ThumbMultilib,
1490                   DefaultMultilib)
1491           .makeMultilibSet()
1492           .FilterOut(NonExistent);
1493 
1494   Multilib::flags_list Flags;
1495   llvm::StringRef Arch = Args.getLastArgValue(options::OPT_march_EQ);
1496   bool IsArmArch = TargetTriple.getArch() == llvm::Triple::arm;
1497   bool IsThumbArch = TargetTriple.getArch() == llvm::Triple::thumb;
1498   bool IsV7SubArch = TargetTriple.getSubArch() == llvm::Triple::ARMSubArch_v7;
1499   bool IsThumbMode = IsThumbArch ||
1500       Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, false) ||
1501       (IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::ISAKind::THUMB);
1502   bool IsArmV7Mode = (IsArmArch || IsThumbArch) &&
1503       (llvm::ARM::parseArchVersion(Arch) == 7 ||
1504        (IsArmArch && Arch == "" && IsV7SubArch));
1505   addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);
1506   addMultilibFlag(IsThumbMode, "-mthumb", Flags);
1507 
1508   if (AndroidArmMultilibs.select(D, Flags, Result.SelectedMultilibs))
1509     Result.Multilibs = AndroidArmMultilibs;
1510 }
1511 
findMSP430Multilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1512 static bool findMSP430Multilibs(const Driver &D,
1513                                 const llvm::Triple &TargetTriple,
1514                                 StringRef Path, const ArgList &Args,
1515                                 DetectedMultilibs &Result) {
1516   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1517   MultilibBuilder WithoutExceptions =
1518       MultilibBuilder("/430").flag("-exceptions", /*Disallow=*/true);
1519   MultilibBuilder WithExceptions =
1520       MultilibBuilder("/430/exceptions").flag("-exceptions");
1521 
1522   // FIXME: when clang starts to support msp430x ISA additional logic
1523   // to select between multilib must be implemented
1524   // MultilibBuilder MSP430xMultilib = MultilibBuilder("/large");
1525 
1526   Result.Multilibs.push_back(WithoutExceptions.makeMultilib());
1527   Result.Multilibs.push_back(WithExceptions.makeMultilib());
1528   Result.Multilibs.FilterOut(NonExistent);
1529 
1530   Multilib::flags_list Flags;
1531   addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,
1532                                options::OPT_fno_exceptions, false),
1533                   "-exceptions", Flags);
1534   if (Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
1535     return true;
1536 
1537   return false;
1538 }
1539 
findCSKYMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1540 static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
1541                               StringRef Path, const ArgList &Args,
1542                               DetectedMultilibs &Result) {
1543   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1544 
1545   tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);
1546   std::optional<llvm::StringRef> Res =
1547       tools::csky::getCSKYArchName(D, Args, TargetTriple);
1548 
1549   if (!Res)
1550     return;
1551   auto ARCHName = *Res;
1552 
1553   Multilib::flags_list Flags;
1554   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "-hard-fp",
1555                   Flags);
1556   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "-soft-fp",
1557                   Flags);
1558   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "-soft", Flags);
1559   addMultilibFlag(ARCHName == "ck801", "-march=ck801", Flags);
1560   addMultilibFlag(ARCHName == "ck802", "-march=ck802", Flags);
1561   addMultilibFlag(ARCHName == "ck803", "-march=ck803", Flags);
1562   addMultilibFlag(ARCHName == "ck804", "-march=ck804", Flags);
1563   addMultilibFlag(ARCHName == "ck805", "-march=ck805", Flags);
1564   addMultilibFlag(ARCHName == "ck807", "-march=ck807", Flags);
1565   addMultilibFlag(ARCHName == "ck810", "-march=ck810", Flags);
1566   addMultilibFlag(ARCHName == "ck810v", "-march=ck810v", Flags);
1567   addMultilibFlag(ARCHName == "ck860", "-march=ck860", Flags);
1568   addMultilibFlag(ARCHName == "ck860v", "-march=ck860v", Flags);
1569 
1570   bool isBigEndian = false;
1571   if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
1572                                options::OPT_mbig_endian))
1573     isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
1574   addMultilibFlag(isBigEndian, "-EB", Flags);
1575 
1576   auto HardFloat = MultilibBuilder("/hard-fp").flag("-hard-fp");
1577   auto SoftFpFloat = MultilibBuilder("/soft-fp").flag("-soft-fp");
1578   auto SoftFloat = MultilibBuilder("").flag("-soft");
1579   auto Arch801 = MultilibBuilder("/ck801").flag("-march=ck801");
1580   auto Arch802 = MultilibBuilder("/ck802").flag("-march=ck802");
1581   auto Arch803 = MultilibBuilder("/ck803").flag("-march=ck803");
1582   // CK804 use the same library as CK803
1583   auto Arch804 = MultilibBuilder("/ck803").flag("-march=ck804");
1584   auto Arch805 = MultilibBuilder("/ck805").flag("-march=ck805");
1585   auto Arch807 = MultilibBuilder("/ck807").flag("-march=ck807");
1586   auto Arch810 = MultilibBuilder("").flag("-march=ck810");
1587   auto Arch810v = MultilibBuilder("/ck810v").flag("-march=ck810v");
1588   auto Arch860 = MultilibBuilder("/ck860").flag("-march=ck860");
1589   auto Arch860v = MultilibBuilder("/ck860v").flag("-march=ck860v");
1590   auto BigEndian = MultilibBuilder("/big").flag("-EB");
1591 
1592   MultilibSet CSKYMultilibs =
1593       MultilibSetBuilder()
1594           .Maybe(BigEndian)
1595           .Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,
1596                    Arch810, Arch810v, Arch860, Arch860v})
1597           .Either(HardFloat, SoftFpFloat, SoftFloat)
1598           .makeMultilibSet()
1599           .FilterOut(NonExistent);
1600 
1601   if (CSKYMultilibs.select(D, Flags, Result.SelectedMultilibs))
1602     Result.Multilibs = CSKYMultilibs;
1603 }
1604 
1605 /// Extend the multi-lib re-use selection mechanism for RISC-V.
1606 /// This function will try to re-use multi-lib if they are compatible.
1607 /// Definition of compatible:
1608 ///   - ABI must be the same.
1609 ///   - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im
1610 ///     is a subset of march=rv32imc.
1611 ///   - march that contains atomic extension can't reuse multi-lib that
1612 ///     doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and
1613 ///     march=rv32ima are not compatible, because software and hardware
1614 ///     atomic operation can't work together correctly.
1615 static bool
selectRISCVMultilib(const Driver & D,const MultilibSet & RISCVMultilibSet,StringRef Arch,const Multilib::flags_list & Flags,llvm::SmallVectorImpl<Multilib> & SelectedMultilibs)1616 selectRISCVMultilib(const Driver &D, const MultilibSet &RISCVMultilibSet,
1617                     StringRef Arch, const Multilib::flags_list &Flags,
1618                     llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {
1619   // Try to find the perfect matching multi-lib first.
1620   if (RISCVMultilibSet.select(D, Flags, SelectedMultilibs))
1621     return true;
1622 
1623   Multilib::flags_list NewFlags;
1624   std::vector<MultilibBuilder> NewMultilibs;
1625 
1626   llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult =
1627       llvm::RISCVISAInfo::parseArchString(
1628           Arch, /*EnableExperimentalExtension=*/true,
1629           /*ExperimentalExtensionVersionCheck=*/false);
1630   // Ignore any error here, we assume it will be handled in another place.
1631   if (llvm::errorToBool(ParseResult.takeError()))
1632     return false;
1633 
1634   auto &ISAInfo = *ParseResult;
1635 
1636   addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags);
1637   addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags);
1638 
1639   // Collect all flags except march=*
1640   for (StringRef Flag : Flags) {
1641     if (Flag.starts_with("!march=") || Flag.starts_with("-march="))
1642       continue;
1643 
1644     NewFlags.push_back(Flag.str());
1645   }
1646 
1647   llvm::StringSet<> AllArchExts;
1648   // Reconstruct multi-lib list, and break march option into separated
1649   // extension. e.g. march=rv32im -> +i +m
1650   for (const auto &M : RISCVMultilibSet) {
1651     bool Skip = false;
1652 
1653     MultilibBuilder NewMultilib =
1654         MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix());
1655     for (StringRef Flag : M.flags()) {
1656       // Add back all flags except -march.
1657       if (!Flag.consume_front("-march=")) {
1658         NewMultilib.flag(Flag);
1659         continue;
1660       }
1661 
1662       // Break down -march into individual extension.
1663       llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult =
1664           llvm::RISCVISAInfo::parseArchString(
1665               Flag, /*EnableExperimentalExtension=*/true,
1666               /*ExperimentalExtensionVersionCheck=*/false);
1667       // Ignore any error here, we assume it will handled in another place.
1668       if (llvm::errorToBool(MLConfigParseResult.takeError())) {
1669         // We might get a parsing error if rv32e in the list, we could just skip
1670         // that and process the rest of multi-lib configs.
1671         Skip = true;
1672         continue;
1673       }
1674       auto &MLConfigISAInfo = *MLConfigParseResult;
1675 
1676       for (auto &MLConfigArchExt : MLConfigISAInfo->getExtensions()) {
1677         auto ExtName = MLConfigArchExt.first;
1678         NewMultilib.flag(Twine("-", ExtName).str());
1679 
1680         if (AllArchExts.insert(ExtName).second) {
1681           addMultilibFlag(ISAInfo->hasExtension(ExtName),
1682                           Twine("-", ExtName).str(), NewFlags);
1683         }
1684       }
1685 
1686       // Check the XLEN explicitly.
1687       if (MLConfigISAInfo->getXLen() == 32) {
1688         NewMultilib.flag("-m32");
1689         NewMultilib.flag("-m64", /*Disallow*/ true);
1690       } else {
1691         NewMultilib.flag("-m32", /*Disallow*/ true);
1692         NewMultilib.flag("-m64");
1693       }
1694 
1695       // Atomic extension must be explicitly checked, soft and hard atomic
1696       // operation never co-work correctly.
1697       if (!MLConfigISAInfo->hasExtension("a"))
1698         NewMultilib.flag("-a", /*Disallow*/ true);
1699     }
1700 
1701     if (Skip)
1702       continue;
1703 
1704     NewMultilibs.emplace_back(NewMultilib);
1705   }
1706 
1707   // Build an internal used only multi-lib list, used for checking any
1708   // compatible multi-lib.
1709   MultilibSet NewRISCVMultilibs =
1710       MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();
1711 
1712   if (NewRISCVMultilibs.select(D, NewFlags, SelectedMultilibs))
1713     for (const Multilib &NewSelectedM : SelectedMultilibs)
1714       for (const auto &M : RISCVMultilibSet)
1715         // Look up the corresponding multi-lib entry in original multi-lib set.
1716         if (M.gccSuffix() == NewSelectedM.gccSuffix())
1717           return true;
1718 
1719   return false;
1720 }
1721 
findRISCVBareMetalMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1722 static void findRISCVBareMetalMultilibs(const Driver &D,
1723                                         const llvm::Triple &TargetTriple,
1724                                         StringRef Path, const ArgList &Args,
1725                                         DetectedMultilibs &Result) {
1726   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1727   struct RiscvMultilib {
1728     StringRef march;
1729     StringRef mabi;
1730   };
1731   // currently only support the set of multilibs like riscv-gnu-toolchain does.
1732   // TODO: support MULTILIB_REUSE
1733   constexpr RiscvMultilib RISCVMultilibSet[] = {
1734       {"rv32i", "ilp32"},     {"rv32im", "ilp32"},     {"rv32iac", "ilp32"},
1735       {"rv32imac", "ilp32"},  {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
1736       {"rv64imafdc", "lp64d"}};
1737 
1738   std::vector<MultilibBuilder> Ms;
1739   for (auto Element : RISCVMultilibSet) {
1740     // multilib path rule is ${march}/${mabi}
1741     Ms.emplace_back(
1742         MultilibBuilder(
1743             (Twine(Element.march) + "/" + Twine(Element.mabi)).str())
1744             .flag(Twine("-march=", Element.march).str())
1745             .flag(Twine("-mabi=", Element.mabi).str()));
1746   }
1747   MultilibSet RISCVMultilibs =
1748       MultilibSetBuilder()
1749           .Either(Ms)
1750           .makeMultilibSet()
1751           .FilterOut(NonExistent)
1752           .setFilePathsCallback([](const Multilib &M) {
1753             return std::vector<std::string>(
1754                 {M.gccSuffix(),
1755                  "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),
1756                  "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
1757           });
1758 
1759   Multilib::flags_list Flags;
1760   llvm::StringSet<> Added_ABIs;
1761   StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
1762   std::string MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
1763   for (auto Element : RISCVMultilibSet) {
1764     addMultilibFlag(MArch == Element.march,
1765                     Twine("-march=", Element.march).str().c_str(), Flags);
1766     if (!Added_ABIs.count(Element.mabi)) {
1767       Added_ABIs.insert(Element.mabi);
1768       addMultilibFlag(ABIName == Element.mabi,
1769                       Twine("-mabi=", Element.mabi).str().c_str(), Flags);
1770     }
1771   }
1772 
1773   if (selectRISCVMultilib(D, RISCVMultilibs, MArch, Flags,
1774                           Result.SelectedMultilibs))
1775     Result.Multilibs = RISCVMultilibs;
1776 }
1777 
findRISCVMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)1778 static void findRISCVMultilibs(const Driver &D,
1779                                const llvm::Triple &TargetTriple, StringRef Path,
1780                                const ArgList &Args, DetectedMultilibs &Result) {
1781   if (TargetTriple.getOS() == llvm::Triple::UnknownOS)
1782     return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);
1783 
1784   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1785   MultilibBuilder Ilp32 =
1786       MultilibBuilder("lib32/ilp32").flag("-m32").flag("-mabi=ilp32");
1787   MultilibBuilder Ilp32f =
1788       MultilibBuilder("lib32/ilp32f").flag("-m32").flag("-mabi=ilp32f");
1789   MultilibBuilder Ilp32d =
1790       MultilibBuilder("lib32/ilp32d").flag("-m32").flag("-mabi=ilp32d");
1791   MultilibBuilder Lp64 =
1792       MultilibBuilder("lib64/lp64").flag("-m64").flag("-mabi=lp64");
1793   MultilibBuilder Lp64f =
1794       MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");
1795   MultilibBuilder Lp64d =
1796       MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");
1797   MultilibSet RISCVMultilibs =
1798       MultilibSetBuilder()
1799           .Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
1800           .makeMultilibSet()
1801           .FilterOut(NonExistent);
1802 
1803   Multilib::flags_list Flags;
1804   bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
1805   StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
1806 
1807   addMultilibFlag(!IsRV64, "-m32", Flags);
1808   addMultilibFlag(IsRV64, "-m64", Flags);
1809   addMultilibFlag(ABIName == "ilp32", "-mabi=ilp32", Flags);
1810   addMultilibFlag(ABIName == "ilp32f", "-mabi=ilp32f", Flags);
1811   addMultilibFlag(ABIName == "ilp32d", "-mabi=ilp32d", Flags);
1812   addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);
1813   addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
1814   addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
1815 
1816   if (RISCVMultilibs.select(D, Flags, Result.SelectedMultilibs))
1817     Result.Multilibs = RISCVMultilibs;
1818 }
1819 
findBiarchMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,bool NeedsBiarchSuffix,DetectedMultilibs & Result)1820 static bool findBiarchMultilibs(const Driver &D,
1821                                 const llvm::Triple &TargetTriple,
1822                                 StringRef Path, const ArgList &Args,
1823                                 bool NeedsBiarchSuffix,
1824                                 DetectedMultilibs &Result) {
1825   MultilibBuilder DefaultBuilder;
1826 
1827   // Some versions of SUSE and Fedora on ppc64 put 32-bit libs
1828   // in what would normally be GCCInstallPath and put the 64-bit
1829   // libs in a subdirectory named 64. The simple logic we follow is that
1830   // *if* there is a subdirectory of the right name with crtbegin.o in it,
1831   // we use that. If not, and if not a biarch triple alias, we look for
1832   // crtbegin.o without the subdirectory.
1833 
1834   StringRef Suff64 = "/64";
1835   // Solaris uses platform-specific suffixes instead of /64.
1836   if (TargetTriple.isOSSolaris()) {
1837     switch (TargetTriple.getArch()) {
1838     case llvm::Triple::x86:
1839     case llvm::Triple::x86_64:
1840       Suff64 = "/amd64";
1841       break;
1842     case llvm::Triple::sparc:
1843     case llvm::Triple::sparcv9:
1844       Suff64 = "/sparcv9";
1845       break;
1846     default:
1847       break;
1848     }
1849   }
1850 
1851   Multilib Alt64 = MultilibBuilder()
1852                        .gccSuffix(Suff64)
1853                        .includeSuffix(Suff64)
1854                        .flag("-m32", /*Disallow=*/true)
1855                        .flag("-m64")
1856                        .flag("-mx32", /*Disallow=*/true)
1857                        .makeMultilib();
1858   Multilib Alt32 = MultilibBuilder()
1859                        .gccSuffix("/32")
1860                        .includeSuffix("/32")
1861                        .flag("-m32")
1862                        .flag("-m64", /*Disallow=*/true)
1863                        .flag("-mx32", /*Disallow=*/true)
1864                        .makeMultilib();
1865   Multilib Altx32 = MultilibBuilder()
1866                         .gccSuffix("/x32")
1867                         .includeSuffix("/x32")
1868                         .flag("-m32", /*Disallow=*/true)
1869                         .flag("-m64", /*Disallow=*/true)
1870                         .flag("-mx32")
1871                         .makeMultilib();
1872   Multilib Alt32sparc = MultilibBuilder()
1873                             .gccSuffix("/sparcv8plus")
1874                             .includeSuffix("/sparcv8plus")
1875                             .flag("-m32")
1876                             .flag("-m64", /*Disallow=*/true)
1877                             .makeMultilib();
1878 
1879   // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.
1880   FilterNonExistent NonExistent(
1881       Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", D.getVFS());
1882 
1883   // Determine default multilib from: 32, 64, x32
1884   // Also handle cases such as 64 on 32, 32 on 64, etc.
1885   enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;
1886   const bool IsX32 = TargetTriple.isX32();
1887   if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
1888     Want = WANT64;
1889   if (TargetTriple.isArch32Bit() && !NonExistent(Alt32sparc))
1890     Want = WANT64;
1891   else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
1892     Want = WANT64;
1893   else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64))
1894     Want = WANT32;
1895   else if (TargetTriple.isArch64Bit() && !NonExistent(Alt32sparc))
1896     Want = WANT64;
1897   else {
1898     if (TargetTriple.isArch32Bit())
1899       Want = NeedsBiarchSuffix ? WANT64 : WANT32;
1900     else if (IsX32)
1901       Want = NeedsBiarchSuffix ? WANT64 : WANTX32;
1902     else
1903       Want = NeedsBiarchSuffix ? WANT32 : WANT64;
1904   }
1905 
1906   if (Want == WANT32)
1907     DefaultBuilder.flag("-m32")
1908         .flag("-m64", /*Disallow=*/true)
1909         .flag("-mx32", /*Disallow=*/true);
1910   else if (Want == WANT64)
1911     DefaultBuilder.flag("-m32", /*Disallow=*/true)
1912         .flag("-m64")
1913         .flag("-mx32", /*Disallow=*/true);
1914   else if (Want == WANTX32)
1915     DefaultBuilder.flag("-m32", /*Disallow=*/true)
1916         .flag("-m64", /*Disallow=*/true)
1917         .flag("-mx32");
1918   else
1919     return false;
1920 
1921   Multilib Default = DefaultBuilder.makeMultilib();
1922 
1923   Result.Multilibs.push_back(Default);
1924   Result.Multilibs.push_back(Alt64);
1925   Result.Multilibs.push_back(Alt32);
1926   Result.Multilibs.push_back(Altx32);
1927   Result.Multilibs.push_back(Alt32sparc);
1928 
1929   Result.Multilibs.FilterOut(NonExistent);
1930 
1931   Multilib::flags_list Flags;
1932   addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "-m64", Flags);
1933   addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);
1934   addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);
1935 
1936   if (!Result.Multilibs.select(D, Flags, Result.SelectedMultilibs))
1937     return false;
1938 
1939   if (Result.SelectedMultilibs.back() == Alt64 ||
1940       Result.SelectedMultilibs.back() == Alt32 ||
1941       Result.SelectedMultilibs.back() == Altx32 ||
1942       Result.SelectedMultilibs.back() == Alt32sparc)
1943     Result.BiarchSibling = Default;
1944 
1945   return true;
1946 }
1947 
1948 /// Generic_GCC - A tool chain using the 'gcc' command to perform
1949 /// all subcommands; this relies on gcc translating the majority of
1950 /// command line options.
1951 
1952 /// Less-than for GCCVersion, implementing a Strict Weak Ordering.
isOlderThan(int RHSMajor,int RHSMinor,int RHSPatch,StringRef RHSPatchSuffix) const1953 bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
1954                                           int RHSPatch,
1955                                           StringRef RHSPatchSuffix) const {
1956   if (Major != RHSMajor)
1957     return Major < RHSMajor;
1958   if (Minor != RHSMinor) {
1959     // Note that versions without a specified minor sort higher than those with
1960     // a minor.
1961     if (RHSMinor == -1)
1962       return true;
1963     if (Minor == -1)
1964       return false;
1965     return Minor < RHSMinor;
1966   }
1967   if (Patch != RHSPatch) {
1968     // Note that versions without a specified patch sort higher than those with
1969     // a patch.
1970     if (RHSPatch == -1)
1971       return true;
1972     if (Patch == -1)
1973       return false;
1974 
1975     // Otherwise just sort on the patch itself.
1976     return Patch < RHSPatch;
1977   }
1978   if (PatchSuffix != RHSPatchSuffix) {
1979     // Sort empty suffixes higher.
1980     if (RHSPatchSuffix.empty())
1981       return true;
1982     if (PatchSuffix.empty())
1983       return false;
1984 
1985     // Provide a lexicographic sort to make this a total ordering.
1986     return PatchSuffix < RHSPatchSuffix;
1987   }
1988 
1989   // The versions are equal.
1990   return false;
1991 }
1992 
1993 /// Parse a GCCVersion object out of a string of text.
1994 ///
1995 /// This is the primary means of forming GCCVersion objects.
1996 /*static*/
Parse(StringRef VersionText)1997 Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
1998   const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
1999   std::pair<StringRef, StringRef> First = VersionText.split('.');
2000   std::pair<StringRef, StringRef> Second = First.second.split('.');
2001 
2002   StringRef MajorStr = First.first;
2003   StringRef MinorStr = Second.first;
2004   StringRef PatchStr = Second.second;
2005 
2006   GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
2007 
2008   // Parse version number strings such as:
2009   //   5
2010   //   4.4
2011   //   4.4-patched
2012   //   4.4.0
2013   //   4.4.x
2014   //   4.4.2-rc4
2015   //   4.4.x-patched
2016   //   10-win32
2017   // Split on '.', handle 1, 2 or 3 such segments. Each segment must contain
2018   // purely a number, except for the last one, where a non-number suffix
2019   // is stored in PatchSuffix. The third segment is allowed to not contain
2020   // a number at all.
2021 
2022   auto TryParseLastNumber = [&](StringRef Segment, int &Number,
2023                                 std::string &OutStr) -> bool {
2024     // Look for a number prefix and parse that, and split out any trailing
2025     // string into GoodVersion.PatchSuffix.
2026 
2027     if (size_t EndNumber = Segment.find_first_not_of("0123456789")) {
2028       StringRef NumberStr = Segment.slice(0, EndNumber);
2029       if (NumberStr.getAsInteger(10, Number) || Number < 0)
2030         return false;
2031       OutStr = NumberStr;
2032       GoodVersion.PatchSuffix = Segment.substr(EndNumber);
2033       return true;
2034     }
2035     return false;
2036   };
2037   auto TryParseNumber = [](StringRef Segment, int &Number) -> bool {
2038     if (Segment.getAsInteger(10, Number) || Number < 0)
2039       return false;
2040     return true;
2041   };
2042 
2043   if (MinorStr.empty()) {
2044     // If no minor string, major is the last segment
2045     if (!TryParseLastNumber(MajorStr, GoodVersion.Major, GoodVersion.MajorStr))
2046       return BadVersion;
2047     return GoodVersion;
2048   }
2049 
2050   if (!TryParseNumber(MajorStr, GoodVersion.Major))
2051     return BadVersion;
2052   GoodVersion.MajorStr = MajorStr;
2053 
2054   if (PatchStr.empty()) {
2055     // If no patch string, minor is the last segment
2056     if (!TryParseLastNumber(MinorStr, GoodVersion.Minor, GoodVersion.MinorStr))
2057       return BadVersion;
2058     return GoodVersion;
2059   }
2060 
2061   if (!TryParseNumber(MinorStr, GoodVersion.Minor))
2062     return BadVersion;
2063   GoodVersion.MinorStr = MinorStr;
2064 
2065   // For the last segment, tolerate a missing number.
2066   std::string DummyStr;
2067   TryParseLastNumber(PatchStr, GoodVersion.Patch, DummyStr);
2068   return GoodVersion;
2069 }
2070 
getGCCToolchainDir(const ArgList & Args,llvm::StringRef SysRoot)2071 static llvm::StringRef getGCCToolchainDir(const ArgList &Args,
2072                                           llvm::StringRef SysRoot) {
2073   const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
2074   if (A)
2075     return A->getValue();
2076 
2077   // If we have a SysRoot, ignore GCC_INSTALL_PREFIX.
2078   // GCC_INSTALL_PREFIX specifies the gcc installation for the default
2079   // sysroot and is likely not valid with a different sysroot.
2080   if (!SysRoot.empty())
2081     return "";
2082 
2083   return GCC_INSTALL_PREFIX;
2084 }
2085 
2086 /// Initialize a GCCInstallationDetector from the driver.
2087 ///
2088 /// This performs all of the autodetection and sets up the various paths.
2089 /// Once constructed, a GCCInstallationDetector is essentially immutable.
2090 ///
2091 /// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
2092 /// should instead pull the target out of the driver. This is currently
2093 /// necessary because the driver doesn't store the final version of the target
2094 /// triple.
init(const llvm::Triple & TargetTriple,const ArgList & Args)2095 void Generic_GCC::GCCInstallationDetector::init(
2096     const llvm::Triple &TargetTriple, const ArgList &Args) {
2097   llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
2098                                          ? TargetTriple.get64BitArchVariant()
2099                                          : TargetTriple.get32BitArchVariant();
2100   // The library directories which may contain GCC installations.
2101   SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
2102   // The compatible GCC triples for this particular architecture.
2103   SmallVector<StringRef, 16> CandidateTripleAliases;
2104   SmallVector<StringRef, 16> CandidateBiarchTripleAliases;
2105   // Add some triples that we want to check first.
2106   CandidateTripleAliases.push_back(TargetTriple.str());
2107   std::string TripleNoVendor, BiarchTripleNoVendor;
2108   if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) {
2109     StringRef OSEnv = TargetTriple.getOSAndEnvironmentName();
2110     if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32)
2111       OSEnv = "linux-gnu";
2112     TripleNoVendor = (TargetTriple.getArchName().str() + '-' + OSEnv).str();
2113     CandidateTripleAliases.push_back(TripleNoVendor);
2114     if (BiarchVariantTriple.getArch() != llvm::Triple::UnknownArch) {
2115       BiarchTripleNoVendor =
2116           (BiarchVariantTriple.getArchName().str() + '-' + OSEnv).str();
2117       CandidateBiarchTripleAliases.push_back(BiarchTripleNoVendor);
2118     }
2119   }
2120 
2121   CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
2122                            CandidateTripleAliases, CandidateBiarchLibDirs,
2123                            CandidateBiarchTripleAliases);
2124 
2125   // If --gcc-install-dir= is specified, skip filesystem detection.
2126   if (const Arg *A =
2127           Args.getLastArg(clang::driver::options::OPT_gcc_install_dir_EQ);
2128       A && A->getValue()[0]) {
2129     StringRef InstallDir = A->getValue();
2130     if (!ScanGCCForMultilibs(TargetTriple, Args, InstallDir, false)) {
2131       D.Diag(diag::err_drv_invalid_gcc_install_dir) << InstallDir;
2132     } else {
2133       (void)InstallDir.consume_back("/");
2134       StringRef VersionText = llvm::sys::path::filename(InstallDir);
2135       StringRef TripleText =
2136           llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
2137 
2138       Version = GCCVersion::Parse(VersionText);
2139       GCCTriple.setTriple(TripleText);
2140       GCCInstallPath = std::string(InstallDir);
2141       GCCParentLibPath = GCCInstallPath + "/../../..";
2142       IsValid = true;
2143     }
2144     return;
2145   }
2146 
2147   // If --gcc-triple is specified use this instead of trying to
2148   // auto-detect a triple.
2149   if (const Arg *A =
2150           Args.getLastArg(clang::driver::options::OPT_gcc_triple_EQ)) {
2151     StringRef GCCTriple = A->getValue();
2152     CandidateTripleAliases.clear();
2153     CandidateTripleAliases.push_back(GCCTriple);
2154   }
2155 
2156   // Compute the set of prefixes for our search.
2157   SmallVector<std::string, 8> Prefixes;
2158   StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
2159   if (GCCToolchainDir != "") {
2160     if (GCCToolchainDir.back() == '/')
2161       GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
2162 
2163     Prefixes.push_back(std::string(GCCToolchainDir));
2164   } else {
2165     // If we have a SysRoot, try that first.
2166     if (!D.SysRoot.empty()) {
2167       Prefixes.push_back(D.SysRoot);
2168       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
2169     }
2170 
2171     // Then look for gcc installed alongside clang.
2172     Prefixes.push_back(D.Dir + "/..");
2173 
2174     // Next, look for prefix(es) that correspond to distribution-supplied gcc
2175     // installations.
2176     if (D.SysRoot.empty()) {
2177       // Typically /usr.
2178       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
2179     }
2180 
2181     // Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.
2182     // This avoids accidentally enforcing the system GCC version when using a
2183     // custom toolchain.
2184     SmallVector<StringRef, 16> GentooTestTriples;
2185     // Try to match an exact triple as target triple first.
2186     // e.g. crossdev -S x86_64-gentoo-linux-gnu will install gcc libs for
2187     // x86_64-gentoo-linux-gnu. But "clang -target x86_64-gentoo-linux-gnu"
2188     // may pick the libraries for x86_64-pc-linux-gnu even when exact matching
2189     // triple x86_64-gentoo-linux-gnu is present.
2190     GentooTestTriples.push_back(TargetTriple.str());
2191     GentooTestTriples.append(CandidateTripleAliases.begin(),
2192                              CandidateTripleAliases.end());
2193     if (ScanGentooConfigs(TargetTriple, Args, GentooTestTriples,
2194                           CandidateBiarchTripleAliases))
2195       return;
2196   }
2197 
2198   // Loop over the various components which exist and select the best GCC
2199   // installation available. GCC installs are ranked by version number.
2200   const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
2201   Version = VersionZero;
2202   for (const std::string &Prefix : Prefixes) {
2203     auto &VFS = D.getVFS();
2204     if (!VFS.exists(Prefix))
2205       continue;
2206     for (StringRef Suffix : CandidateLibDirs) {
2207       const std::string LibDir = concat(Prefix, Suffix);
2208       if (!VFS.exists(LibDir))
2209         continue;
2210       // Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.
2211       bool GCCDirExists = VFS.exists(LibDir + "/gcc");
2212       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
2213       for (StringRef Candidate : CandidateTripleAliases)
2214         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,
2215                                GCCDirExists, GCCCrossDirExists);
2216     }
2217     for (StringRef Suffix : CandidateBiarchLibDirs) {
2218       const std::string LibDir = Prefix + Suffix.str();
2219       if (!VFS.exists(LibDir))
2220         continue;
2221       bool GCCDirExists = VFS.exists(LibDir + "/gcc");
2222       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
2223       for (StringRef Candidate : CandidateBiarchTripleAliases)
2224         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,
2225                                GCCDirExists, GCCCrossDirExists);
2226     }
2227 
2228     // Skip other prefixes once a GCC installation is found.
2229     if (Version > VersionZero)
2230       break;
2231   }
2232 }
2233 
print(raw_ostream & OS) const2234 void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
2235   for (const auto &InstallPath : CandidateGCCInstallPaths)
2236     OS << "Found candidate GCC installation: " << InstallPath << "\n";
2237 
2238   if (!GCCInstallPath.empty())
2239     OS << "Selected GCC installation: " << GCCInstallPath << "\n";
2240 
2241   for (const auto &Multilib : Multilibs)
2242     OS << "Candidate multilib: " << Multilib << "\n";
2243 
2244   if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
2245     OS << "Selected multilib: " << SelectedMultilib << "\n";
2246 }
2247 
getBiarchSibling(Multilib & M) const2248 bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
2249   if (BiarchSibling) {
2250     M = *BiarchSibling;
2251     return true;
2252   }
2253   return false;
2254 }
2255 
AddDefaultGCCPrefixes(const llvm::Triple & TargetTriple,SmallVectorImpl<std::string> & Prefixes,StringRef SysRoot)2256 void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
2257     const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes,
2258     StringRef SysRoot) {
2259 
2260   if (TargetTriple.isOSHaiku()) {
2261     Prefixes.push_back(concat(SysRoot, "/boot/system/develop/tools"));
2262     return;
2263   }
2264 
2265   if (TargetTriple.isOSSolaris()) {
2266     // Solaris is a special case.
2267     // The GCC installation is under
2268     //   /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/
2269     // so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
2270     // /usr/gcc/<version> as a prefix.
2271 
2272     SmallVector<std::pair<GCCVersion, std::string>, 8> SolarisPrefixes;
2273     std::string PrefixDir = concat(SysRoot, "/usr/gcc");
2274     std::error_code EC;
2275     for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
2276                                        LE;
2277          !EC && LI != LE; LI = LI.increment(EC)) {
2278       StringRef VersionText = llvm::sys::path::filename(LI->path());
2279       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
2280 
2281       // Filter out obviously bad entries.
2282       if (CandidateVersion.Major == -1 || CandidateVersion.isOlderThan(4, 1, 1))
2283         continue;
2284 
2285       std::string CandidatePrefix = PrefixDir + "/" + VersionText.str();
2286       std::string CandidateLibPath = CandidatePrefix + "/lib/gcc";
2287       if (!D.getVFS().exists(CandidateLibPath))
2288         continue;
2289 
2290       SolarisPrefixes.emplace_back(
2291           std::make_pair(CandidateVersion, CandidatePrefix));
2292     }
2293     // Sort in reverse order so GCCInstallationDetector::init picks the latest.
2294     std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend());
2295     for (auto p : SolarisPrefixes)
2296       Prefixes.emplace_back(p.second);
2297     return;
2298   }
2299 
2300   // For Linux, if --sysroot is not specified, look for RHEL/CentOS devtoolsets
2301   // and gcc-toolsets.
2302   if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
2303       D.getVFS().exists("/opt/rh")) {
2304     // TODO: We may want to remove this, since the functionality
2305     //   can be achieved using config files.
2306     Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr");
2307     Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");
2308     Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
2309     Prefixes.push_back("/opt/rh/devtoolset-12/root/usr");
2310     Prefixes.push_back("/opt/rh/devtoolset-11/root/usr");
2311     Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");
2312     Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
2313     Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
2314     Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
2315     Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
2316     Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
2317     Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
2318     Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
2319   }
2320 
2321   // Fall back to /usr which is used by most non-Solaris systems.
2322   Prefixes.push_back(concat(SysRoot, "/usr"));
2323 }
2324 
CollectLibDirsAndTriples(const llvm::Triple & TargetTriple,const llvm::Triple & BiarchTriple,SmallVectorImpl<StringRef> & LibDirs,SmallVectorImpl<StringRef> & TripleAliases,SmallVectorImpl<StringRef> & BiarchLibDirs,SmallVectorImpl<StringRef> & BiarchTripleAliases)2325 /*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
2326     const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
2327     SmallVectorImpl<StringRef> &LibDirs,
2328     SmallVectorImpl<StringRef> &TripleAliases,
2329     SmallVectorImpl<StringRef> &BiarchLibDirs,
2330     SmallVectorImpl<StringRef> &BiarchTripleAliases) {
2331   // Declare a bunch of static data sets that we'll select between below. These
2332   // are specifically designed to always refer to string literals to avoid any
2333   // lifetime or initialization issues.
2334   //
2335   // The *Triples variables hard code some triples so that, for example,
2336   // --target=aarch64 (incomplete triple) can detect lib/aarch64-linux-gnu.
2337   // They are not needed when the user has correct LLVM_DEFAULT_TARGET_TRIPLE
2338   // and always uses the full --target (e.g. --target=aarch64-linux-gnu).  The
2339   // lists should shrink over time. Please don't add more elements to *Triples.
2340   static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
2341   static const char *const AArch64Triples[] = {
2342       "aarch64-none-linux-gnu", "aarch64-redhat-linux", "aarch64-suse-linux"};
2343   static const char *const AArch64beLibDirs[] = {"/lib"};
2344   static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu"};
2345 
2346   static const char *const ARMLibDirs[] = {"/lib"};
2347   static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
2348   static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
2349                                              "armv7hl-redhat-linux-gnueabi",
2350                                              "armv6hl-suse-linux-gnueabi",
2351                                              "armv7hl-suse-linux-gnueabi"};
2352   static const char *const ARMebLibDirs[] = {"/lib"};
2353   static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
2354   static const char *const ARMebHFTriples[] = {
2355       "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
2356 
2357   static const char *const AVRLibDirs[] = {"/lib"};
2358   static const char *const AVRTriples[] = {"avr"};
2359 
2360   static const char *const CSKYLibDirs[] = {"/lib"};
2361   static const char *const CSKYTriples[] = {
2362       "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};
2363 
2364   static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
2365   static const char *const X86_64Triples[] = {
2366       "x86_64-linux-gnu",       "x86_64-unknown-linux-gnu",
2367       "x86_64-pc-linux-gnu",    "x86_64-redhat-linux6E",
2368       "x86_64-redhat-linux",    "x86_64-suse-linux",
2369       "x86_64-manbo-linux-gnu", "x86_64-slackware-linux",
2370       "x86_64-unknown-linux",   "x86_64-amazon-linux"};
2371   static const char *const X32Triples[] = {"x86_64-linux-gnux32",
2372                                            "x86_64-pc-linux-gnux32"};
2373   static const char *const X32LibDirs[] = {"/libx32", "/lib"};
2374   static const char *const X86LibDirs[] = {"/lib32", "/lib"};
2375   static const char *const X86Triples[] = {
2376       "i586-linux-gnu",      "i686-linux-gnu",        "i686-pc-linux-gnu",
2377       "i386-redhat-linux6E", "i686-redhat-linux",     "i386-redhat-linux",
2378       "i586-suse-linux",     "i686-montavista-linux",
2379   };
2380 
2381   static const char *const LoongArch64LibDirs[] = {"/lib64", "/lib"};
2382   static const char *const LoongArch64Triples[] = {
2383       "loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"};
2384 
2385   static const char *const M68kLibDirs[] = {"/lib"};
2386   static const char *const M68kTriples[] = {"m68k-unknown-linux-gnu",
2387                                             "m68k-suse-linux"};
2388 
2389   static const char *const MIPSLibDirs[] = {"/libo32", "/lib"};
2390   static const char *const MIPSTriples[] = {
2391       "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
2392       "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
2393   static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"};
2394   static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
2395                                               "mips-img-linux-gnu"};
2396 
2397   static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
2398   static const char *const MIPS64Triples[] = {
2399       "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64-linux-gnuabi64",
2400       "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};
2401   static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
2402   static const char *const MIPS64ELTriples[] = {
2403       "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64el-linux-gnuabi64",
2404       "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"};
2405 
2406   static const char *const MIPSN32LibDirs[] = {"/lib32"};
2407   static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",
2408                                                "mipsisa64r6-linux-gnuabin32"};
2409   static const char *const MIPSN32ELLibDirs[] = {"/lib32"};
2410   static const char *const MIPSN32ELTriples[] = {
2411       "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"};
2412 
2413   static const char *const MSP430LibDirs[] = {"/lib"};
2414   static const char *const MSP430Triples[] = {"msp430-elf"};
2415 
2416   static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
2417   static const char *const PPCTriples[] = {
2418       "powerpc-unknown-linux-gnu",
2419       // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a
2420       // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".
2421       "powerpc64-suse-linux", "powerpc-montavista-linuxspe"};
2422   static const char *const PPCLELibDirs[] = {"/lib32", "/lib"};
2423   static const char *const PPCLETriples[] = {"powerpcle-unknown-linux-gnu",
2424                                              "powerpcle-linux-musl"};
2425 
2426   static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};
2427   static const char *const PPC64Triples[] = {"powerpc64-unknown-linux-gnu",
2428                                              "powerpc64-suse-linux",
2429                                              "ppc64-redhat-linux"};
2430   static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"};
2431   static const char *const PPC64LETriples[] = {
2432       "powerpc64le-unknown-linux-gnu", "powerpc64le-none-linux-gnu",
2433       "powerpc64le-suse-linux", "ppc64le-redhat-linux"};
2434 
2435   static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"};
2436   static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",
2437                                                "riscv32-unknown-elf"};
2438   static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
2439   static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
2440                                                "riscv64-unknown-elf"};
2441 
2442   static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
2443   static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
2444                                                "sparcv8-linux-gnu"};
2445   static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
2446   static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
2447                                                "sparcv9-linux-gnu"};
2448 
2449   static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
2450   static const char *const SystemZTriples[] = {
2451       "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux",
2452       "s390x-redhat-linux"};
2453 
2454   using std::begin;
2455   using std::end;
2456 
2457   if (TargetTriple.isOSSolaris()) {
2458     static const char *const SolarisLibDirs[] = {"/lib"};
2459     static const char *const SolarisSparcV8Triples[] = {
2460         "sparc-sun-solaris2.11"};
2461     static const char *const SolarisSparcV9Triples[] = {
2462         "sparcv9-sun-solaris2.11"};
2463     static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11"};
2464     static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11"};
2465     LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
2466     BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
2467     switch (TargetTriple.getArch()) {
2468     case llvm::Triple::x86:
2469       TripleAliases.append(begin(SolarisX86Triples), end(SolarisX86Triples));
2470       BiarchTripleAliases.append(begin(SolarisX86_64Triples),
2471                                  end(SolarisX86_64Triples));
2472       break;
2473     case llvm::Triple::x86_64:
2474       TripleAliases.append(begin(SolarisX86_64Triples),
2475                            end(SolarisX86_64Triples));
2476       BiarchTripleAliases.append(begin(SolarisX86Triples),
2477                                  end(SolarisX86Triples));
2478       break;
2479     case llvm::Triple::sparc:
2480       TripleAliases.append(begin(SolarisSparcV8Triples),
2481                            end(SolarisSparcV8Triples));
2482       BiarchTripleAliases.append(begin(SolarisSparcV9Triples),
2483                                  end(SolarisSparcV9Triples));
2484       break;
2485     case llvm::Triple::sparcv9:
2486       TripleAliases.append(begin(SolarisSparcV9Triples),
2487                            end(SolarisSparcV9Triples));
2488       BiarchTripleAliases.append(begin(SolarisSparcV8Triples),
2489                                  end(SolarisSparcV8Triples));
2490       break;
2491     default:
2492       break;
2493     }
2494     return;
2495   }
2496 
2497   // Android targets should not use GNU/Linux tools or libraries.
2498   if (TargetTriple.isAndroid()) {
2499     static const char *const AArch64AndroidTriples[] = {
2500         "aarch64-linux-android"};
2501     static const char *const ARMAndroidTriples[] = {"arm-linux-androideabi"};
2502     static const char *const X86AndroidTriples[] = {"i686-linux-android"};
2503     static const char *const X86_64AndroidTriples[] = {"x86_64-linux-android"};
2504 
2505     switch (TargetTriple.getArch()) {
2506     case llvm::Triple::aarch64:
2507       LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
2508       TripleAliases.append(begin(AArch64AndroidTriples),
2509                            end(AArch64AndroidTriples));
2510       break;
2511     case llvm::Triple::arm:
2512     case llvm::Triple::thumb:
2513       LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
2514       TripleAliases.append(begin(ARMAndroidTriples), end(ARMAndroidTriples));
2515       break;
2516     case llvm::Triple::x86_64:
2517       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2518       TripleAliases.append(begin(X86_64AndroidTriples),
2519                            end(X86_64AndroidTriples));
2520       BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
2521       BiarchTripleAliases.append(begin(X86AndroidTriples),
2522                                  end(X86AndroidTriples));
2523       break;
2524     case llvm::Triple::x86:
2525       LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
2526       TripleAliases.append(begin(X86AndroidTriples), end(X86AndroidTriples));
2527       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2528       BiarchTripleAliases.append(begin(X86_64AndroidTriples),
2529                                  end(X86_64AndroidTriples));
2530       break;
2531     default:
2532       break;
2533     }
2534 
2535     return;
2536   }
2537 
2538   if (TargetTriple.isOSHurd()) {
2539     switch (TargetTriple.getArch()) {
2540     case llvm::Triple::x86_64:
2541       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2542       TripleAliases.push_back("x86_64-gnu");
2543       break;
2544     case llvm::Triple::x86:
2545       LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
2546       TripleAliases.push_back("i686-gnu");
2547       break;
2548     default:
2549       break;
2550     }
2551 
2552     return;
2553   }
2554 
2555   if (TargetTriple.isWindowsCygwinEnvironment()) {
2556     LibDirs.push_back("/lib");
2557     switch (TargetTriple.getArch()) {
2558     case llvm::Triple::x86_64:
2559       TripleAliases.append({"x86_64-pc-cygwin", "x86_64-pc-msys"});
2560       break;
2561     case llvm::Triple::x86:
2562       TripleAliases.append({"i686-pc-cygwin", "i686-pc-msys"});
2563       break;
2564     default:
2565       break;
2566     }
2567 
2568     return;
2569   }
2570 
2571   switch (TargetTriple.getArch()) {
2572   case llvm::Triple::aarch64:
2573     LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
2574     TripleAliases.append(begin(AArch64Triples), end(AArch64Triples));
2575     BiarchLibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
2576     BiarchTripleAliases.append(begin(AArch64Triples), end(AArch64Triples));
2577     break;
2578   case llvm::Triple::aarch64_be:
2579     LibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));
2580     TripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));
2581     BiarchLibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));
2582     BiarchTripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));
2583     break;
2584   case llvm::Triple::arm:
2585   case llvm::Triple::thumb:
2586     LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
2587     if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
2588         TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
2589         TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
2590         TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
2591       TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));
2592     } else {
2593       TripleAliases.append(begin(ARMTriples), end(ARMTriples));
2594     }
2595     break;
2596   case llvm::Triple::armeb:
2597   case llvm::Triple::thumbeb:
2598     LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));
2599     if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
2600         TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
2601         TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
2602         TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
2603       TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));
2604     } else {
2605       TripleAliases.append(begin(ARMebTriples), end(ARMebTriples));
2606     }
2607     break;
2608   case llvm::Triple::avr:
2609     LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));
2610     TripleAliases.append(begin(AVRTriples), end(AVRTriples));
2611     break;
2612   case llvm::Triple::csky:
2613     LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));
2614     TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));
2615     break;
2616   case llvm::Triple::x86_64:
2617     if (TargetTriple.isX32()) {
2618       LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2619       TripleAliases.append(begin(X32Triples), end(X32Triples));
2620       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2621       BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
2622     } else {
2623       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2624       TripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
2625       BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2626       BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
2627     }
2628     BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
2629     BiarchTripleAliases.append(begin(X86Triples), end(X86Triples));
2630     break;
2631   case llvm::Triple::x86:
2632     LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
2633     // MCU toolchain is 32 bit only and its triple alias is TargetTriple
2634     // itself, which will be appended below.
2635     if (!TargetTriple.isOSIAMCU()) {
2636       TripleAliases.append(begin(X86Triples), end(X86Triples));
2637       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2638       BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
2639       BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2640       BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
2641     }
2642     break;
2643   // TODO: Handle loongarch32.
2644   case llvm::Triple::loongarch64:
2645     LibDirs.append(begin(LoongArch64LibDirs), end(LoongArch64LibDirs));
2646     TripleAliases.append(begin(LoongArch64Triples), end(LoongArch64Triples));
2647     break;
2648   case llvm::Triple::m68k:
2649     LibDirs.append(begin(M68kLibDirs), end(M68kLibDirs));
2650     TripleAliases.append(begin(M68kTriples), end(M68kTriples));
2651     break;
2652   case llvm::Triple::mips:
2653     LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
2654     TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
2655     BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
2656     BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
2657     BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
2658     BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
2659     break;
2660   case llvm::Triple::mipsel:
2661     LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
2662     TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
2663     TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
2664     BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
2665     BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
2666     BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
2667     BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
2668     break;
2669   case llvm::Triple::mips64:
2670     LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
2671     TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
2672     BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
2673     BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
2674     BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
2675     BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
2676     break;
2677   case llvm::Triple::mips64el:
2678     LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
2679     TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
2680     BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
2681     BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
2682     BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
2683     BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
2684     BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
2685     break;
2686   case llvm::Triple::msp430:
2687     LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs));
2688     TripleAliases.append(begin(MSP430Triples), end(MSP430Triples));
2689     break;
2690   case llvm::Triple::ppc:
2691     LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
2692     TripleAliases.append(begin(PPCTriples), end(PPCTriples));
2693     BiarchLibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));
2694     BiarchTripleAliases.append(begin(PPC64Triples), end(PPC64Triples));
2695     break;
2696   case llvm::Triple::ppcle:
2697     LibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));
2698     TripleAliases.append(begin(PPCLETriples), end(PPCLETriples));
2699     BiarchLibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
2700     BiarchTripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
2701     break;
2702   case llvm::Triple::ppc64:
2703     LibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));
2704     TripleAliases.append(begin(PPC64Triples), end(PPC64Triples));
2705     BiarchLibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
2706     BiarchTripleAliases.append(begin(PPCTriples), end(PPCTriples));
2707     break;
2708   case llvm::Triple::ppc64le:
2709     LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
2710     TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
2711     BiarchLibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));
2712     BiarchTripleAliases.append(begin(PPCLETriples), end(PPCLETriples));
2713     break;
2714   case llvm::Triple::riscv32:
2715     LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
2716     TripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));
2717     BiarchLibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));
2718     BiarchTripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));
2719     break;
2720   case llvm::Triple::riscv64:
2721     LibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));
2722     TripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));
2723     BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
2724     BiarchTripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));
2725     break;
2726   case llvm::Triple::sparc:
2727   case llvm::Triple::sparcel:
2728     LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
2729     TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));
2730     BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));
2731     BiarchTripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));
2732     break;
2733   case llvm::Triple::sparcv9:
2734     LibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));
2735     TripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));
2736     BiarchLibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
2737     BiarchTripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));
2738     break;
2739   case llvm::Triple::systemz:
2740     LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs));
2741     TripleAliases.append(begin(SystemZTriples), end(SystemZTriples));
2742     break;
2743   default:
2744     // By default, just rely on the standard lib directories and the original
2745     // triple.
2746     break;
2747   }
2748 
2749   // Also include the multiarch variant if it's different.
2750   if (TargetTriple.str() != BiarchTriple.str())
2751     BiarchTripleAliases.push_back(BiarchTriple.str());
2752 }
2753 
ScanGCCForMultilibs(const llvm::Triple & TargetTriple,const ArgList & Args,StringRef Path,bool NeedsBiarchSuffix)2754 bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
2755     const llvm::Triple &TargetTriple, const ArgList &Args,
2756     StringRef Path, bool NeedsBiarchSuffix) {
2757   llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
2758   DetectedMultilibs Detected;
2759 
2760   // Android standalone toolchain could have multilibs for ARM and Thumb.
2761   // Debian mips multilibs behave more like the rest of the biarch ones,
2762   // so handle them there
2763   if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
2764     // It should also work without multilibs in a simplified toolchain.
2765     findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
2766   } else if (TargetTriple.isCSKY()) {
2767     findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);
2768   } else if (TargetTriple.isMIPS()) {
2769     if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
2770       return false;
2771   } else if (TargetTriple.isRISCV()) {
2772     findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
2773   } else if (isMSP430(TargetArch)) {
2774     findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);
2775   } else if (TargetArch == llvm::Triple::avr) {
2776     // AVR has no multilibs.
2777   } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
2778                                   NeedsBiarchSuffix, Detected)) {
2779     return false;
2780   }
2781 
2782   Multilibs = Detected.Multilibs;
2783   SelectedMultilib = Detected.SelectedMultilibs.empty()
2784                          ? Multilib()
2785                          : Detected.SelectedMultilibs.back();
2786   BiarchSibling = Detected.BiarchSibling;
2787 
2788   return true;
2789 }
2790 
ScanLibDirForGCCTriple(const llvm::Triple & TargetTriple,const ArgList & Args,const std::string & LibDir,StringRef CandidateTriple,bool NeedsBiarchSuffix,bool GCCDirExists,bool GCCCrossDirExists)2791 void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
2792     const llvm::Triple &TargetTriple, const ArgList &Args,
2793     const std::string &LibDir, StringRef CandidateTriple,
2794     bool NeedsBiarchSuffix, bool GCCDirExists, bool GCCCrossDirExists) {
2795   // Locations relative to the system lib directory where GCC's triple-specific
2796   // directories might reside.
2797   struct GCCLibSuffix {
2798     // Path from system lib directory to GCC triple-specific directory.
2799     std::string LibSuffix;
2800     // Path from GCC triple-specific directory back to system lib directory.
2801     // This is one '..' component per component in LibSuffix.
2802     StringRef ReversePath;
2803     // Whether this library suffix is relevant for the triple.
2804     bool Active;
2805   } Suffixes[] = {
2806       // This is the normal place.
2807       {"gcc/" + CandidateTriple.str(), "../..", GCCDirExists},
2808 
2809       // Debian puts cross-compilers in gcc-cross.
2810       {"gcc-cross/" + CandidateTriple.str(), "../..", GCCCrossDirExists},
2811 
2812       // The Freescale PPC SDK has the gcc libraries in
2813       // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do
2814       // this on Freescale triples, though, since some systems put a *lot* of
2815       // files in that location, not just GCC installation data.
2816       {CandidateTriple.str(), "..",
2817        TargetTriple.getVendor() == llvm::Triple::Freescale ||
2818            TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
2819 
2820   for (auto &Suffix : Suffixes) {
2821     if (!Suffix.Active)
2822       continue;
2823 
2824     StringRef LibSuffix = Suffix.LibSuffix;
2825     std::error_code EC;
2826     for (llvm::vfs::directory_iterator
2827              LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),
2828              LE;
2829          !EC && LI != LE; LI = LI.increment(EC)) {
2830       StringRef VersionText = llvm::sys::path::filename(LI->path());
2831       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
2832       if (CandidateVersion.Major != -1) // Filter obviously bad entries.
2833         if (!CandidateGCCInstallPaths.insert(std::string(LI->path())).second)
2834           continue; // Saw this path before; no need to look at it again.
2835       if (CandidateVersion.isOlderThan(4, 1, 1))
2836         continue;
2837       if (CandidateVersion <= Version)
2838         continue;
2839 
2840       if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
2841                                NeedsBiarchSuffix))
2842         continue;
2843 
2844       Version = CandidateVersion;
2845       GCCTriple.setTriple(CandidateTriple);
2846       // FIXME: We hack together the directory name here instead of
2847       // using LI to ensure stable path separators across Windows and
2848       // Linux.
2849       GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
2850       GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
2851       IsValid = true;
2852     }
2853   }
2854 }
2855 
ScanGentooConfigs(const llvm::Triple & TargetTriple,const ArgList & Args,const SmallVectorImpl<StringRef> & CandidateTriples,const SmallVectorImpl<StringRef> & CandidateBiarchTriples)2856 bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
2857     const llvm::Triple &TargetTriple, const ArgList &Args,
2858     const SmallVectorImpl<StringRef> &CandidateTriples,
2859     const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
2860   if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))
2861     return false;
2862 
2863   for (StringRef CandidateTriple : CandidateTriples) {
2864     if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))
2865       return true;
2866   }
2867 
2868   for (StringRef CandidateTriple : CandidateBiarchTriples) {
2869     if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true))
2870       return true;
2871   }
2872   return false;
2873 }
2874 
ScanGentooGccConfig(const llvm::Triple & TargetTriple,const ArgList & Args,StringRef CandidateTriple,bool NeedsBiarchSuffix)2875 bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
2876     const llvm::Triple &TargetTriple, const ArgList &Args,
2877     StringRef CandidateTriple, bool NeedsBiarchSuffix) {
2878   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
2879       D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,
2880                                          "/config-" + CandidateTriple.str()));
2881   if (File) {
2882     SmallVector<StringRef, 2> Lines;
2883     File.get()->getBuffer().split(Lines, "\n");
2884     for (StringRef Line : Lines) {
2885       Line = Line.trim();
2886       // CURRENT=triple-version
2887       if (!Line.consume_front("CURRENT="))
2888         continue;
2889       // Process the config file pointed to by CURRENT.
2890       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
2891           D.getVFS().getBufferForFile(
2892               concat(D.SysRoot, GentooConfigDir, "/" + Line));
2893       std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
2894       // List of paths to scan for libraries.
2895       SmallVector<StringRef, 4> GentooScanPaths;
2896       // Scan the Config file to find installed GCC libraries path.
2897       // Typical content of the GCC config file:
2898       // LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x:/usr/lib/gcc/
2899       // (continued from previous line) x86_64-pc-linux-gnu/4.9.x/32"
2900       // MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/man"
2901       // INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/info"
2902       // STDCXX_INCDIR="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4"
2903       // We are looking for the paths listed in LDPATH=... .
2904       if (ConfigFile) {
2905         SmallVector<StringRef, 2> ConfigLines;
2906         ConfigFile.get()->getBuffer().split(ConfigLines, "\n");
2907         for (StringRef ConfLine : ConfigLines) {
2908           ConfLine = ConfLine.trim();
2909           if (ConfLine.consume_front("LDPATH=")) {
2910             // Drop '"' from front and back if present.
2911             ConfLine.consume_back("\"");
2912             ConfLine.consume_front("\"");
2913             // Get all paths sperated by ':'
2914             ConfLine.split(GentooScanPaths, ':', -1, /*AllowEmpty*/ false);
2915           }
2916         }
2917       }
2918       // Test the path based on the version in /etc/env.d/gcc/config-{tuple}.
2919       std::string basePath = "/usr/lib/gcc/" + ActiveVersion.first.str() + "/"
2920           + ActiveVersion.second.str();
2921       GentooScanPaths.push_back(StringRef(basePath));
2922 
2923       // Scan all paths for GCC libraries.
2924       for (const auto &GentooScanPath : GentooScanPaths) {
2925         std::string GentooPath = concat(D.SysRoot, GentooScanPath);
2926         if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
2927           if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
2928                                    NeedsBiarchSuffix))
2929             continue;
2930 
2931           Version = GCCVersion::Parse(ActiveVersion.second);
2932           GCCInstallPath = GentooPath;
2933           GCCParentLibPath = GentooPath + std::string("/../../..");
2934           GCCTriple.setTriple(ActiveVersion.first);
2935           IsValid = true;
2936           return true;
2937         }
2938       }
2939     }
2940   }
2941 
2942   return false;
2943 }
2944 
Generic_GCC(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)2945 Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
2946                          const ArgList &Args)
2947     : ToolChain(D, Triple, Args), GCCInstallation(D),
2948       CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args),
2949       SYCLInstallation(D, Triple, Args) {
2950   getProgramPaths().push_back(getDriver().Dir);
2951 }
2952 
~Generic_GCC()2953 Generic_GCC::~Generic_GCC() {}
2954 
getTool(Action::ActionClass AC) const2955 Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
2956   switch (AC) {
2957   case Action::PreprocessJobClass:
2958     if (!Preprocess)
2959       Preprocess.reset(new clang::driver::tools::gcc::Preprocessor(*this));
2960     return Preprocess.get();
2961   case Action::CompileJobClass:
2962     if (!Compile)
2963       Compile.reset(new tools::gcc::Compiler(*this));
2964     return Compile.get();
2965   default:
2966     return ToolChain::getTool(AC);
2967   }
2968 }
2969 
buildAssembler() const2970 Tool *Generic_GCC::buildAssembler() const {
2971   return new tools::gnutools::Assembler(*this);
2972 }
2973 
buildLinker() const2974 Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
2975 
printVerboseInfo(raw_ostream & OS) const2976 void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
2977   // Print the information about how we detected the GCC installation.
2978   GCCInstallation.print(OS);
2979   CudaInstallation->print(OS);
2980   RocmInstallation->print(OS);
2981 }
2982 
2983 ToolChain::UnwindTableLevel
getDefaultUnwindTableLevel(const ArgList & Args) const2984 Generic_GCC::getDefaultUnwindTableLevel(const ArgList &Args) const {
2985   switch (getArch()) {
2986   case llvm::Triple::aarch64:
2987   case llvm::Triple::aarch64_be:
2988   case llvm::Triple::ppc:
2989   case llvm::Triple::ppcle:
2990   case llvm::Triple::ppc64:
2991   case llvm::Triple::ppc64le:
2992   case llvm::Triple::riscv32:
2993   case llvm::Triple::riscv64:
2994   case llvm::Triple::x86:
2995   case llvm::Triple::x86_64:
2996     return UnwindTableLevel::Asynchronous;
2997   default:
2998     return UnwindTableLevel::None;
2999   }
3000 }
3001 
isPICDefault() const3002 bool Generic_GCC::isPICDefault() const {
3003   switch (getArch()) {
3004   case llvm::Triple::x86_64:
3005     return getTriple().isOSWindows();
3006   case llvm::Triple::mips64:
3007   case llvm::Triple::mips64el:
3008     return true;
3009   default:
3010     return false;
3011   }
3012 }
3013 
isPIEDefault(const llvm::opt::ArgList & Args) const3014 bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const {
3015   return false;
3016 }
3017 
isPICDefaultForced() const3018 bool Generic_GCC::isPICDefaultForced() const {
3019   return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
3020 }
3021 
IsIntegratedAssemblerDefault() const3022 bool Generic_GCC::IsIntegratedAssemblerDefault() const {
3023   switch (getTriple().getArch()) {
3024   case llvm::Triple::nvptx:
3025   case llvm::Triple::nvptx64:
3026   case llvm::Triple::xcore:
3027     return false;
3028   default:
3029     return true;
3030   }
3031 }
3032 
PushPPaths(ToolChain::path_list & PPaths)3033 void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {
3034   // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
3035   // least) put various tools in a triple-prefixed directory off of the parent
3036   // of the GCC installation. We use the GCC triple here to ensure that we end
3037   // up with tools that support the same amount of cross compiling as the
3038   // detected GCC installation. For example, if we find a GCC installation
3039   // targeting x86_64, but it is a bi-arch GCC installation, it can also be
3040   // used to target i386.
3041   if (GCCInstallation.isValid()) {
3042     PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
3043                            GCCInstallation.getTriple().str() + "/bin")
3044                          .str());
3045   }
3046 }
3047 
AddMultilibPaths(const Driver & D,const std::string & SysRoot,const std::string & OSLibDir,const std::string & MultiarchTriple,path_list & Paths)3048 void Generic_GCC::AddMultilibPaths(const Driver &D,
3049                                    const std::string &SysRoot,
3050                                    const std::string &OSLibDir,
3051                                    const std::string &MultiarchTriple,
3052                                    path_list &Paths) {
3053   // Add the multilib suffixed paths where they are available.
3054   if (GCCInstallation.isValid()) {
3055     assert(!SelectedMultilibs.empty());
3056     const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
3057     const std::string &LibPath =
3058         std::string(GCCInstallation.getParentLibPath());
3059 
3060     // Sourcery CodeBench MIPS toolchain holds some libraries under
3061     // a biarch-like suffix of the GCC installation.
3062     if (const auto &PathsCallback = Multilibs.filePathsCallback())
3063       for (const auto &Path : PathsCallback(SelectedMultilibs.back()))
3064         addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);
3065 
3066     // Add lib/gcc/$triple/$version, with an optional /multilib suffix.
3067     addPathIfExists(D,
3068                     GCCInstallation.getInstallPath() +
3069                         SelectedMultilibs.back().gccSuffix(),
3070                     Paths);
3071 
3072     // Add lib/gcc/$triple/$libdir
3073     // For GCC built with --enable-version-specific-runtime-libs.
3074     addPathIfExists(D, GCCInstallation.getInstallPath() + "/../" + OSLibDir,
3075                     Paths);
3076 
3077     // GCC cross compiling toolchains will install target libraries which ship
3078     // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
3079     // any part of the GCC installation in
3080     // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
3081     // debatable, but is the reality today. We need to search this tree even
3082     // when we have a sysroot somewhere else. It is the responsibility of
3083     // whomever is doing the cross build targeting a sysroot using a GCC
3084     // installation that is *not* within the system root to ensure two things:
3085     //
3086     //  1) Any DSOs that are linked in from this tree or from the install path
3087     //     above must be present on the system root and found via an
3088     //     appropriate rpath.
3089     //  2) There must not be libraries installed into
3090     //     <prefix>/<triple>/<libdir> unless they should be preferred over
3091     //     those within the system root.
3092     //
3093     // Note that this matches the GCC behavior. See the below comment for where
3094     // Clang diverges from GCC's behavior.
3095     addPathIfExists(D,
3096                     LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
3097                         SelectedMultilibs.back().osSuffix(),
3098                     Paths);
3099 
3100     // If the GCC installation we found is inside of the sysroot, we want to
3101     // prefer libraries installed in the parent prefix of the GCC installation.
3102     // It is important to *not* use these paths when the GCC installation is
3103     // outside of the system root as that can pick up unintended libraries.
3104     // This usually happens when there is an external cross compiler on the
3105     // host system, and a more minimal sysroot available that is the target of
3106     // the cross. Note that GCC does include some of these directories in some
3107     // configurations but this seems somewhere between questionable and simply
3108     // a bug.
3109     if (StringRef(LibPath).starts_with(SysRoot))
3110       addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
3111   }
3112 }
3113 
AddMultiarchPaths(const Driver & D,const std::string & SysRoot,const std::string & OSLibDir,path_list & Paths)3114 void Generic_GCC::AddMultiarchPaths(const Driver &D,
3115                                     const std::string &SysRoot,
3116                                     const std::string &OSLibDir,
3117                                     path_list &Paths) {
3118   if (GCCInstallation.isValid()) {
3119     const std::string &LibPath =
3120         std::string(GCCInstallation.getParentLibPath());
3121     const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
3122     const Multilib &Multilib = GCCInstallation.getMultilib();
3123     addPathIfExists(
3124         D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),
3125                     Paths);
3126   }
3127 }
3128 
AddMultilibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const3129 void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
3130                                          ArgStringList &CC1Args) const {
3131   // Add include directories specific to the selected multilib set and multilib.
3132   if (!GCCInstallation.isValid())
3133     return;
3134   // gcc TOOL_INCLUDE_DIR.
3135   const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
3136   std::string LibPath(GCCInstallation.getParentLibPath());
3137   addSystemInclude(DriverArgs, CC1Args,
3138                    Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
3139 
3140   const auto &Callback = Multilibs.includeDirsCallback();
3141   if (Callback) {
3142     for (const auto &Path : Callback(GCCInstallation.getMultilib()))
3143       addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
3144                                       GCCInstallation.getInstallPath() + Path);
3145   }
3146 }
3147 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const3148 void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
3149                                                ArgStringList &CC1Args) const {
3150   if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
3151                         options::OPT_nostdlibinc))
3152     return;
3153 
3154   switch (GetCXXStdlibType(DriverArgs)) {
3155   case ToolChain::CST_Libcxx:
3156     addLibCxxIncludePaths(DriverArgs, CC1Args);
3157     break;
3158 
3159   case ToolChain::CST_Libstdcxx:
3160     addLibStdCxxIncludePaths(DriverArgs, CC1Args);
3161     break;
3162   }
3163 }
3164 
addSYCLIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const3165 void Generic_GCC::addSYCLIncludeArgs(const ArgList &DriverArgs,
3166                                      ArgStringList &CC1Args) const {
3167   SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);
3168 }
3169 
3170 void
addLibCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const3171 Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
3172                                    llvm::opt::ArgStringList &CC1Args) const {
3173   const Driver &D = getDriver();
3174   std::string SysRoot = computeSysRoot();
3175   if (SysRoot.empty())
3176     SysRoot = llvm::sys::path::get_separator();
3177 
3178   auto AddIncludePath = [&](StringRef Path, bool TargetDirRequired = false) {
3179     std::string Version = detectLibcxxVersion(Path);
3180     if (Version.empty())
3181       return false;
3182 
3183     // First add the per-target include path if it exists.
3184     bool TargetDirExists = false;
3185     std::optional<std::string> TargetIncludeDir = getTargetSubDirPath(Path);
3186     if (TargetIncludeDir) {
3187       SmallString<128> TargetDir(*TargetIncludeDir);
3188       llvm::sys::path::append(TargetDir, "c++", Version);
3189       if (D.getVFS().exists(TargetDir)) {
3190         addSystemInclude(DriverArgs, CC1Args, TargetDir);
3191         TargetDirExists = true;
3192       }
3193     }
3194     if (TargetDirRequired && !TargetDirExists)
3195       return false;
3196 
3197     // Second add the generic one.
3198     SmallString<128> GenericDir(Path);
3199     llvm::sys::path::append(GenericDir, "c++", Version);
3200     addSystemInclude(DriverArgs, CC1Args, GenericDir);
3201     return true;
3202   };
3203 
3204   // Android only uses the libc++ headers installed alongside the toolchain if
3205   // they contain an Android-specific target include path, otherwise they're
3206   // incompatible with the NDK libraries.
3207   SmallString<128> DriverIncludeDir(getDriver().Dir);
3208   llvm::sys::path::append(DriverIncludeDir, "..", "include");
3209   if (AddIncludePath(DriverIncludeDir,
3210                      /*TargetDirRequired=*/getTriple().isAndroid()))
3211     return;
3212   // If this is a development, non-installed, clang, libcxx will
3213   // not be found at ../include/c++ but it likely to be found at
3214   // one of the following two locations:
3215   SmallString<128> UsrLocalIncludeDir(SysRoot);
3216   llvm::sys::path::append(UsrLocalIncludeDir, "usr", "local", "include");
3217   if (AddIncludePath(UsrLocalIncludeDir))
3218     return;
3219   SmallString<128> UsrIncludeDir(SysRoot);
3220   llvm::sys::path::append(UsrIncludeDir, "usr", "include");
3221   if (AddIncludePath(UsrIncludeDir))
3222     return;
3223 }
3224 
addLibStdCXXIncludePaths(Twine IncludeDir,StringRef Triple,Twine IncludeSuffix,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,bool DetectDebian) const3225 bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
3226                                            Twine IncludeSuffix,
3227                                            const llvm::opt::ArgList &DriverArgs,
3228                                            llvm::opt::ArgStringList &CC1Args,
3229                                            bool DetectDebian) const {
3230   if (!getVFS().exists(IncludeDir))
3231     return false;
3232 
3233   // Debian native gcc uses g++-multiarch-incdir.diff which uses
3234   // include/x86_64-linux-gnu/c++/10$IncludeSuffix instead of
3235   // include/c++/10/x86_64-linux-gnu$IncludeSuffix.
3236   std::string Dir = IncludeDir.str();
3237   StringRef Include =
3238       llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));
3239   std::string Path =
3240       (Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
3241           .str();
3242   if (DetectDebian && !getVFS().exists(Path))
3243     return false;
3244 
3245   // GPLUSPLUS_INCLUDE_DIR
3246   addSystemInclude(DriverArgs, CC1Args, IncludeDir);
3247   // GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
3248   // include directory.
3249   if (DetectDebian)
3250     addSystemInclude(DriverArgs, CC1Args, Path);
3251   else if (!Triple.empty())
3252     addSystemInclude(DriverArgs, CC1Args,
3253                      IncludeDir + "/" + Triple + IncludeSuffix);
3254   // GPLUSPLUS_BACKWARD_INCLUDE_DIR
3255   addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
3256   return true;
3257 }
3258 
addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef DebianMultiarch) const3259 bool Generic_GCC::addGCCLibStdCxxIncludePaths(
3260     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3261     StringRef DebianMultiarch) const {
3262   assert(GCCInstallation.isValid());
3263 
3264   // By default, look for the C++ headers in an include directory adjacent to
3265   // the lib directory of the GCC installation. Note that this is expect to be
3266   // equivalent to '/usr/include/c++/X.Y' in almost all cases.
3267   StringRef LibDir = GCCInstallation.getParentLibPath();
3268   StringRef InstallDir = GCCInstallation.getInstallPath();
3269   StringRef TripleStr = GCCInstallation.getTriple().str();
3270   const Multilib &Multilib = GCCInstallation.getMultilib();
3271   const GCCVersion &Version = GCCInstallation.getVersion();
3272 
3273   // Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
3274   if (addLibStdCXXIncludePaths(
3275           LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
3276           TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
3277     return true;
3278 
3279   // Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
3280   // empty). Like above but for GCC built with
3281   // --enable-version-specific-runtime-libs.
3282   if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
3283                                    Version.Text + "/include/c++/",
3284                                TripleStr, Multilib.includeSuffix(), DriverArgs,
3285                                CC1Args))
3286     return true;
3287 
3288   // Detect Debian g++-multiarch-incdir.diff.
3289   if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
3290                                DebianMultiarch, Multilib.includeSuffix(),
3291                                DriverArgs, CC1Args, /*Debian=*/true))
3292     return true;
3293 
3294   // Try /../include/c++/$version (gcc --print-multiarch is empty).
3295   if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
3296                                TripleStr, Multilib.includeSuffix(), DriverArgs,
3297                                CC1Args))
3298     return true;
3299 
3300   // Otherwise, fall back on a bunch of options which don't use multiarch
3301   // layouts for simplicity.
3302   const std::string LibStdCXXIncludePathCandidates[] = {
3303       // Gentoo is weird and places its headers inside the GCC install,
3304       // so if the first attempt to find the headers fails, try these patterns.
3305       InstallDir.str() + "/include/g++-v" + Version.Text,
3306       InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
3307           Version.MinorStr,
3308       InstallDir.str() + "/include/g++-v" + Version.MajorStr,
3309   };
3310 
3311   for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
3312     if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
3313                                  Multilib.includeSuffix(), DriverArgs, CC1Args))
3314       return true;
3315   }
3316   return false;
3317 }
3318 
3319 void
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const3320 Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
3321                                       llvm::opt::ArgStringList &CC1Args) const {
3322   if (GCCInstallation.isValid()) {
3323     addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
3324                                 GCCInstallation.getTriple().str());
3325   }
3326 }
3327 
3328 llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind DeviceOffloadKind) const3329 Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args,
3330                            StringRef BoundArch,
3331                            Action::OffloadKind DeviceOffloadKind) const {
3332   if (DeviceOffloadKind != Action::OFK_SYCL &&
3333       DeviceOffloadKind != Action::OFK_OpenMP)
3334     return nullptr;
3335 
3336   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
3337 
3338   // Filter all the arguments we don't care passing to the offloading
3339   // toolchain as they can mess up with the creation of a shared library.
3340   const llvm::DenseSet<unsigned> OpenMPFiltered{
3341       options::OPT_shared, options::OPT_dynamic, options::OPT_static,
3342       options::OPT_fPIE,   options::OPT_fno_PIE, options::OPT_fpie,
3343       options::OPT_fno_pie};
3344   for (auto *A : Args)
3345     if (DeviceOffloadKind != Action::OFK_OpenMP ||
3346         !OpenMPFiltered.contains(A->getOption().getID()))
3347       DAL->append(A);
3348 
3349   // Request a shared library for CPU offloading. Given that these options
3350   // are decided implicitly, they do not refer to any base argument.
3351   const OptTable &Opts = getDriver().getOpts();
3352   if (DeviceOffloadKind == Action::OFK_OpenMP) {
3353     DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_shared));
3354     DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_fPIC));
3355   }
3356 
3357   // Add the bound architecture to the arguments list if present.
3358   if (!BoundArch.empty()) {
3359     options::ID Opt =
3360         getTriple().isARM() || getTriple().isPPC() || getTriple().isAArch64()
3361             ? options::OPT_mcpu_EQ
3362             : options::OPT_march_EQ;
3363     DAL->eraseArg(Opt);
3364     DAL->AddJoinedArg(nullptr, Opts.getOption(Opt), BoundArch);
3365   }
3366   return DAL;
3367 }
3368 
anchor()3369 void Generic_ELF::anchor() {}
3370 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const3371 void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
3372                                         ArgStringList &CC1Args,
3373                                         Action::OffloadKind) const {
3374   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
3375                           options::OPT_fno_use_init_array, true))
3376     CC1Args.push_back("-fno-use-init-array");
3377 }
3378