xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
10b57cec5SDimitry Andric //===--- Gnu.cpp - Gnu Tool and ToolChain Implementations -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "Gnu.h"
100b57cec5SDimitry Andric #include "Arch/ARM.h"
1181ad6265SDimitry Andric #include "Arch/CSKY.h"
1206c3fb27SDimitry Andric #include "Arch/LoongArch.h"
130b57cec5SDimitry Andric #include "Arch/Mips.h"
140b57cec5SDimitry Andric #include "Arch/PPC.h"
150b57cec5SDimitry Andric #include "Arch/RISCV.h"
160b57cec5SDimitry Andric #include "Arch/Sparc.h"
170b57cec5SDimitry Andric #include "Arch/SystemZ.h"
180b57cec5SDimitry Andric #include "CommonArgs.h"
190b57cec5SDimitry Andric #include "Linux.h"
200b57cec5SDimitry Andric #include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
210b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
220b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
230b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
2406c3fb27SDimitry Andric #include "clang/Driver/MultilibBuilder.h"
250b57cec5SDimitry Andric #include "clang/Driver/Options.h"
260b57cec5SDimitry Andric #include "clang/Driver/Tool.h"
270b57cec5SDimitry Andric #include "clang/Driver/ToolChain.h"
28bdd1243dSDimitry Andric #include "llvm/ADT/StringSet.h"
29bdd1243dSDimitry Andric #include "llvm/ADT/Twine.h"
300b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
310b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
320b57cec5SDimitry Andric #include "llvm/Support/Path.h"
330b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
340fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h"
3506c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h"
360b57cec5SDimitry Andric #include <system_error>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace clang::driver;
390b57cec5SDimitry Andric using namespace clang::driver::toolchains;
400b57cec5SDimitry Andric using namespace clang;
410b57cec5SDimitry Andric using namespace llvm::opt;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using tools::addMultilibFlag;
445ffd83dbSDimitry Andric using tools::addPathIfExists;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric static bool forwardToGCC(const Option &O) {
47e8d8bef9SDimitry Andric   // LinkerInput options have been forwarded. Don't duplicate.
48e8d8bef9SDimitry Andric   if (O.hasFlag(options::LinkerInput))
49e8d8bef9SDimitry Andric     return false;
50e8d8bef9SDimitry Andric   return O.matches(options::OPT_Link_Group) || O.hasFlag(options::LinkOption);
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric // Switch CPU names not recognized by GNU assembler to a close CPU that it does
540b57cec5SDimitry Andric // recognize, instead of a lower march from being picked in the absence of a cpu
550b57cec5SDimitry Andric // flag.
560b57cec5SDimitry Andric static void normalizeCPUNamesForAssembler(const ArgList &Args,
570b57cec5SDimitry Andric                                           ArgStringList &CmdArgs) {
580b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
590b57cec5SDimitry Andric     StringRef CPUArg(A->getValue());
60fe6060f1SDimitry Andric     if (CPUArg.equals_insensitive("krait"))
610b57cec5SDimitry Andric       CmdArgs.push_back("-mcpu=cortex-a15");
62fe6060f1SDimitry Andric     else if (CPUArg.equals_insensitive("kryo"))
630b57cec5SDimitry Andric       CmdArgs.push_back("-mcpu=cortex-a57");
640b57cec5SDimitry Andric     else
650b57cec5SDimitry Andric       Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
700b57cec5SDimitry Andric                                       const InputInfo &Output,
710b57cec5SDimitry Andric                                       const InputInfoList &Inputs,
720b57cec5SDimitry Andric                                       const ArgList &Args,
730b57cec5SDimitry Andric                                       const char *LinkingOutput) const {
740b57cec5SDimitry Andric   const Driver &D = getToolChain().getDriver();
750b57cec5SDimitry Andric   ArgStringList CmdArgs;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   for (const auto &A : Args) {
780b57cec5SDimitry Andric     if (forwardToGCC(A->getOption())) {
790b57cec5SDimitry Andric       // It is unfortunate that we have to claim here, as this means
800b57cec5SDimitry Andric       // we will basically never report anything interesting for
810b57cec5SDimitry Andric       // platforms using a generic gcc, even if we are just using gcc
820b57cec5SDimitry Andric       // to get to the assembler.
830b57cec5SDimitry Andric       A->claim();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric       A->render(Args, CmdArgs);
860b57cec5SDimitry Andric     }
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   RenderExtraToolArgs(JA, CmdArgs);
900b57cec5SDimitry Andric 
91bdd1243dSDimitry Andric   // If using a driver, force the arch.
920b57cec5SDimitry Andric   if (getToolChain().getTriple().isOSDarwin()) {
930b57cec5SDimitry Andric     CmdArgs.push_back("-arch");
940b57cec5SDimitry Andric     CmdArgs.push_back(
950b57cec5SDimitry Andric         Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   // Try to force gcc to match the tool chain we want, if we recognize
990b57cec5SDimitry Andric   // the arch.
1000b57cec5SDimitry Andric   //
1010b57cec5SDimitry Andric   // FIXME: The triple class should directly provide the information we want
1020b57cec5SDimitry Andric   // here.
1030b57cec5SDimitry Andric   switch (getToolChain().getArch()) {
1040b57cec5SDimitry Andric   default:
1050b57cec5SDimitry Andric     break;
1060b57cec5SDimitry Andric   case llvm::Triple::x86:
1070b57cec5SDimitry Andric   case llvm::Triple::ppc:
108e8d8bef9SDimitry Andric   case llvm::Triple::ppcle:
1090b57cec5SDimitry Andric     CmdArgs.push_back("-m32");
1100b57cec5SDimitry Andric     break;
1110b57cec5SDimitry Andric   case llvm::Triple::x86_64:
1120b57cec5SDimitry Andric   case llvm::Triple::ppc64:
1130b57cec5SDimitry Andric   case llvm::Triple::ppc64le:
1140b57cec5SDimitry Andric     CmdArgs.push_back("-m64");
1150b57cec5SDimitry Andric     break;
1160b57cec5SDimitry Andric   case llvm::Triple::sparcel:
1170b57cec5SDimitry Andric     CmdArgs.push_back("-EL");
1180b57cec5SDimitry Andric     break;
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1215f757f3fSDimitry Andric   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
1220b57cec5SDimitry Andric   if (Output.isFilename()) {
1230b57cec5SDimitry Andric     CmdArgs.push_back("-o");
1240b57cec5SDimitry Andric     CmdArgs.push_back(Output.getFilename());
1250b57cec5SDimitry Andric   } else {
1260b57cec5SDimitry Andric     CmdArgs.push_back("-fsyntax-only");
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   // Only pass -x if gcc will understand it; otherwise hope gcc
1320b57cec5SDimitry Andric   // understands the suffix correctly. The main use case this would go
1330b57cec5SDimitry Andric   // wrong in is for linker inputs if they happened to have an odd
1340b57cec5SDimitry Andric   // suffix; really the only way to get this to happen is a command
1350b57cec5SDimitry Andric   // like '-x foobar a.c' which will treat a.c like a linker input.
1360b57cec5SDimitry Andric   //
1370b57cec5SDimitry Andric   // FIXME: For the linker case specifically, can we safely convert
1380b57cec5SDimitry Andric   // inputs into '-Wl,' options?
1390b57cec5SDimitry Andric   for (const auto &II : Inputs) {
1400b57cec5SDimitry Andric     // Don't try to pass LLVM or AST inputs to a generic gcc.
1410b57cec5SDimitry Andric     if (types::isLLVMIR(II.getType()))
1420b57cec5SDimitry Andric       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
1430b57cec5SDimitry Andric           << getToolChain().getTripleString();
1440b57cec5SDimitry Andric     else if (II.getType() == types::TY_AST)
1450b57cec5SDimitry Andric       D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString();
1460b57cec5SDimitry Andric     else if (II.getType() == types::TY_ModuleFile)
1470b57cec5SDimitry Andric       D.Diag(diag::err_drv_no_module_support)
1480b57cec5SDimitry Andric           << getToolChain().getTripleString();
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric     if (types::canTypeBeUserSpecified(II.getType())) {
1510b57cec5SDimitry Andric       CmdArgs.push_back("-x");
1520b57cec5SDimitry Andric       CmdArgs.push_back(types::getTypeName(II.getType()));
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric     if (II.isFilename())
1560b57cec5SDimitry Andric       CmdArgs.push_back(II.getFilename());
1570b57cec5SDimitry Andric     else {
1580b57cec5SDimitry Andric       const Arg &A = II.getInputArg();
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric       // Reverse translate some rewritten options.
1610b57cec5SDimitry Andric       if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
1620b57cec5SDimitry Andric         CmdArgs.push_back("-lstdc++");
1630b57cec5SDimitry Andric         continue;
1640b57cec5SDimitry Andric       }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric       // Don't render as input, we need gcc to do the translations.
1670b57cec5SDimitry Andric       A.render(Args, CmdArgs);
1680b57cec5SDimitry Andric     }
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   const std::string &customGCCName = D.getCCCGenericGCCName();
1720b57cec5SDimitry Andric   const char *GCCName;
1730b57cec5SDimitry Andric   if (!customGCCName.empty())
1740b57cec5SDimitry Andric     GCCName = customGCCName.c_str();
1750b57cec5SDimitry Andric   else if (D.CCCIsCXX()) {
1760b57cec5SDimitry Andric     GCCName = "g++";
1770b57cec5SDimitry Andric   } else
1780b57cec5SDimitry Andric     GCCName = "gcc";
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
181e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
182e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
183e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric void tools::gcc::Preprocessor::RenderExtraToolArgs(
1870b57cec5SDimitry Andric     const JobAction &JA, ArgStringList &CmdArgs) const {
1880b57cec5SDimitry Andric   CmdArgs.push_back("-E");
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric void tools::gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,
1920b57cec5SDimitry Andric                                                ArgStringList &CmdArgs) const {
1930b57cec5SDimitry Andric   const Driver &D = getToolChain().getDriver();
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   switch (JA.getType()) {
1960b57cec5SDimitry Andric   // If -flto, etc. are present then make sure not to force assembly output.
1970b57cec5SDimitry Andric   case types::TY_LLVM_IR:
1980b57cec5SDimitry Andric   case types::TY_LTO_IR:
1990b57cec5SDimitry Andric   case types::TY_LLVM_BC:
2000b57cec5SDimitry Andric   case types::TY_LTO_BC:
2010b57cec5SDimitry Andric     CmdArgs.push_back("-c");
2020b57cec5SDimitry Andric     break;
2030b57cec5SDimitry Andric   // We assume we've got an "integrated" assembler in that gcc will produce an
2040b57cec5SDimitry Andric   // object file itself.
2050b57cec5SDimitry Andric   case types::TY_Object:
2060b57cec5SDimitry Andric     CmdArgs.push_back("-c");
2070b57cec5SDimitry Andric     break;
2080b57cec5SDimitry Andric   case types::TY_PP_Asm:
2090b57cec5SDimitry Andric     CmdArgs.push_back("-S");
2100b57cec5SDimitry Andric     break;
2110b57cec5SDimitry Andric   case types::TY_Nothing:
2120b57cec5SDimitry Andric     CmdArgs.push_back("-fsyntax-only");
2130b57cec5SDimitry Andric     break;
2140b57cec5SDimitry Andric   default:
2150b57cec5SDimitry Andric     D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
2200b57cec5SDimitry Andric                                              ArgStringList &CmdArgs) const {
2210b57cec5SDimitry Andric   // The types are (hopefully) good enough.
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
2250b57cec5SDimitry Andric   switch (T.getArch()) {
2260b57cec5SDimitry Andric   case llvm::Triple::x86:
2270b57cec5SDimitry Andric     if (T.isOSIAMCU())
2280b57cec5SDimitry Andric       return "elf_iamcu";
2290b57cec5SDimitry Andric     return "elf_i386";
2300b57cec5SDimitry Andric   case llvm::Triple::aarch64:
2310b57cec5SDimitry Andric     return "aarch64linux";
2320b57cec5SDimitry Andric   case llvm::Triple::aarch64_be:
2330b57cec5SDimitry Andric     return "aarch64linuxb";
2340b57cec5SDimitry Andric   case llvm::Triple::arm:
2350b57cec5SDimitry Andric   case llvm::Triple::thumb:
2360b57cec5SDimitry Andric   case llvm::Triple::armeb:
2370b57cec5SDimitry Andric   case llvm::Triple::thumbeb:
23806c3fb27SDimitry Andric     return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi"
23906c3fb27SDimitry Andric                                                : "armelf_linux_eabi";
240fe6060f1SDimitry Andric   case llvm::Triple::m68k:
241fe6060f1SDimitry Andric     return "m68kelf";
2420b57cec5SDimitry Andric   case llvm::Triple::ppc:
243e8d8bef9SDimitry Andric     if (T.isOSLinux())
2440b57cec5SDimitry Andric       return "elf32ppclinux";
245e8d8bef9SDimitry Andric     return "elf32ppc";
246e8d8bef9SDimitry Andric   case llvm::Triple::ppcle:
247e8d8bef9SDimitry Andric     if (T.isOSLinux())
248e8d8bef9SDimitry Andric       return "elf32lppclinux";
249e8d8bef9SDimitry Andric     return "elf32lppc";
2500b57cec5SDimitry Andric   case llvm::Triple::ppc64:
2510b57cec5SDimitry Andric     return "elf64ppc";
2520b57cec5SDimitry Andric   case llvm::Triple::ppc64le:
2530b57cec5SDimitry Andric     return "elf64lppc";
2540b57cec5SDimitry Andric   case llvm::Triple::riscv32:
2550b57cec5SDimitry Andric     return "elf32lriscv";
2560b57cec5SDimitry Andric   case llvm::Triple::riscv64:
2570b57cec5SDimitry Andric     return "elf64lriscv";
2580b57cec5SDimitry Andric   case llvm::Triple::sparc:
2590b57cec5SDimitry Andric   case llvm::Triple::sparcel:
2600b57cec5SDimitry Andric     return "elf32_sparc";
2610b57cec5SDimitry Andric   case llvm::Triple::sparcv9:
2620b57cec5SDimitry Andric     return "elf64_sparc";
263bdd1243dSDimitry Andric   case llvm::Triple::loongarch32:
264bdd1243dSDimitry Andric     return "elf32loongarch";
265bdd1243dSDimitry Andric   case llvm::Triple::loongarch64:
266bdd1243dSDimitry Andric     return "elf64loongarch";
2670b57cec5SDimitry Andric   case llvm::Triple::mips:
2680b57cec5SDimitry Andric     return "elf32btsmip";
2690b57cec5SDimitry Andric   case llvm::Triple::mipsel:
2700b57cec5SDimitry Andric     return "elf32ltsmip";
2710b57cec5SDimitry Andric   case llvm::Triple::mips64:
2720b57cec5SDimitry Andric     if (tools::mips::hasMipsAbiArg(Args, "n32") ||
2730b57cec5SDimitry Andric         T.getEnvironment() == llvm::Triple::GNUABIN32)
2740b57cec5SDimitry Andric       return "elf32btsmipn32";
2750b57cec5SDimitry Andric     return "elf64btsmip";
2760b57cec5SDimitry Andric   case llvm::Triple::mips64el:
2770b57cec5SDimitry Andric     if (tools::mips::hasMipsAbiArg(Args, "n32") ||
2780b57cec5SDimitry Andric         T.getEnvironment() == llvm::Triple::GNUABIN32)
2790b57cec5SDimitry Andric       return "elf32ltsmipn32";
2800b57cec5SDimitry Andric     return "elf64ltsmip";
2810b57cec5SDimitry Andric   case llvm::Triple::systemz:
2820b57cec5SDimitry Andric     return "elf64_s390";
2830b57cec5SDimitry Andric   case llvm::Triple::x86_64:
284fe6060f1SDimitry Andric     if (T.isX32())
2850b57cec5SDimitry Andric       return "elf32_x86_64";
2860b57cec5SDimitry Andric     return "elf_x86_64";
2875ffd83dbSDimitry Andric   case llvm::Triple::ve:
2885ffd83dbSDimitry Andric     return "elf64ve";
28981ad6265SDimitry Andric   case llvm::Triple::csky:
29081ad6265SDimitry Andric     return "cskyelf_linux";
2910b57cec5SDimitry Andric   default:
2920b57cec5SDimitry Andric     return nullptr;
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
296d65cd7a5SDimitry Andric static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {
2970b57cec5SDimitry Andric   bool HasStaticPIE = Args.hasArg(options::OPT_static_pie);
2985f757f3fSDimitry Andric   if (HasStaticPIE && Args.hasArg(options::OPT_no_pie)) {
299d65cd7a5SDimitry Andric     const Driver &D = TC.getDriver();
3000b57cec5SDimitry Andric     const llvm::opt::OptTable &Opts = D.getOpts();
301bdd1243dSDimitry Andric     StringRef StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
302bdd1243dSDimitry Andric     StringRef NoPIEName = Opts.getOptionName(options::OPT_nopie);
3030b57cec5SDimitry Andric     D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric   return HasStaticPIE;
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric static bool getStatic(const ArgList &Args) {
3090b57cec5SDimitry Andric   return Args.hasArg(options::OPT_static) &&
3100b57cec5SDimitry Andric       !Args.hasArg(options::OPT_static_pie);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3135ffd83dbSDimitry Andric void tools::gnutools::StaticLibTool::ConstructJob(
3145ffd83dbSDimitry Andric     Compilation &C, const JobAction &JA, const InputInfo &Output,
3155ffd83dbSDimitry Andric     const InputInfoList &Inputs, const ArgList &Args,
3165ffd83dbSDimitry Andric     const char *LinkingOutput) const {
3175ffd83dbSDimitry Andric   const Driver &D = getToolChain().getDriver();
3185ffd83dbSDimitry Andric 
3195ffd83dbSDimitry Andric   // Silence warning for "clang -g foo.o -o foo"
3205ffd83dbSDimitry Andric   Args.ClaimAllArgs(options::OPT_g_Group);
3215ffd83dbSDimitry Andric   // and "clang -emit-llvm foo.o -o foo"
3225ffd83dbSDimitry Andric   Args.ClaimAllArgs(options::OPT_emit_llvm);
3235ffd83dbSDimitry Andric   // and for "clang -w foo.o -o foo". Other warning options are already
3245ffd83dbSDimitry Andric   // handled somewhere else.
3255ffd83dbSDimitry Andric   Args.ClaimAllArgs(options::OPT_w);
3265ffd83dbSDimitry Andric   // Silence warnings when linking C code with a C++ '-stdlib' argument.
3275ffd83dbSDimitry Andric   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
3285ffd83dbSDimitry Andric 
329e8d8bef9SDimitry Andric   // ar tool command "llvm-ar <options> <output_file> <input_files>".
3305ffd83dbSDimitry Andric   ArgStringList CmdArgs;
3315ffd83dbSDimitry Andric   // Create and insert file members with a deterministic index.
3325ffd83dbSDimitry Andric   CmdArgs.push_back("rcsD");
3335ffd83dbSDimitry Andric   CmdArgs.push_back(Output.getFilename());
334e8d8bef9SDimitry Andric 
335e8d8bef9SDimitry Andric   for (const auto &II : Inputs) {
336e8d8bef9SDimitry Andric     if (II.isFilename()) {
337e8d8bef9SDimitry Andric        CmdArgs.push_back(II.getFilename());
338e8d8bef9SDimitry Andric     }
339e8d8bef9SDimitry Andric   }
3405ffd83dbSDimitry Andric 
3415ffd83dbSDimitry Andric   // Delete old output archive file if it already exists before generating a new
3425ffd83dbSDimitry Andric   // archive file.
3435ffd83dbSDimitry Andric   auto OutputFileName = Output.getFilename();
3445ffd83dbSDimitry Andric   if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
3455ffd83dbSDimitry Andric     if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
3465ffd83dbSDimitry Andric       D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
3475ffd83dbSDimitry Andric       return;
3485ffd83dbSDimitry Andric     }
3495ffd83dbSDimitry Andric   }
3505ffd83dbSDimitry Andric 
3515ffd83dbSDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
352e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
353e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
354e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
3555ffd83dbSDimitry Andric }
3565ffd83dbSDimitry Andric 
3570b57cec5SDimitry Andric void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
3580b57cec5SDimitry Andric                                            const InputInfo &Output,
3590b57cec5SDimitry Andric                                            const InputInfoList &Inputs,
3600b57cec5SDimitry Andric                                            const ArgList &Args,
3610b57cec5SDimitry Andric                                            const char *LinkingOutput) const {
362d65cd7a5SDimitry Andric   // FIXME: The Linker class constructor takes a ToolChain and not a
363d65cd7a5SDimitry Andric   // Generic_ELF, so the static_cast might return a reference to a invalid
364d65cd7a5SDimitry Andric   // instance (see PR45061). Ideally, the Linker constructor needs to take a
365d65cd7a5SDimitry Andric   // Generic_ELF instead.
3665f757f3fSDimitry Andric   const auto &ToolChain = static_cast<const Generic_ELF &>(getToolChain());
3670b57cec5SDimitry Andric   const Driver &D = ToolChain.getDriver();
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   const llvm::Triple::ArchType Arch = ToolChain.getArch();
37206c3fb27SDimitry Andric   const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily();
3730b57cec5SDimitry Andric   const bool isAndroid = ToolChain.getTriple().isAndroid();
3740b57cec5SDimitry Andric   const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
3755ffd83dbSDimitry Andric   const bool IsVE = ToolChain.getTriple().isVE();
3760b57cec5SDimitry Andric   const bool IsStaticPIE = getStaticPIE(Args, ToolChain);
3770b57cec5SDimitry Andric   const bool IsStatic = getStatic(Args);
3780b57cec5SDimitry Andric   const bool HasCRTBeginEndFiles =
3790b57cec5SDimitry Andric       ToolChain.getTriple().hasEnvironment() ||
3800b57cec5SDimitry Andric       (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   ArgStringList CmdArgs;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   // Silence warning for "clang -g foo.o -o foo"
3850b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_g_Group);
3860b57cec5SDimitry Andric   // and "clang -emit-llvm foo.o -o foo"
3870b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_emit_llvm);
3880b57cec5SDimitry Andric   // and for "clang -w foo.o -o foo". Other warning options are already
3890b57cec5SDimitry Andric   // handled somewhere else.
3900b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_w);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   if (!D.SysRoot.empty())
3930b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_s))
3960b57cec5SDimitry Andric     CmdArgs.push_back("-s");
3970b57cec5SDimitry Andric 
39806c3fb27SDimitry Andric   if (Triple.isARM() || Triple.isThumb()) {
39906c3fb27SDimitry Andric     bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
4000b57cec5SDimitry Andric     if (IsBigEndian)
4010b57cec5SDimitry Andric       arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
4020b57cec5SDimitry Andric     CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
40306c3fb27SDimitry Andric   } else if (Triple.isAArch64()) {
40406c3fb27SDimitry Andric     CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   // Most Android ARM64 targets should enable the linker fix for erratum
4080b57cec5SDimitry Andric   // 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
40906c3fb27SDimitry Andric   if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) {
410349cc55cSDimitry Andric     std::string CPU = getCPUName(D, Args, Triple);
4110b57cec5SDimitry Andric     if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
4120b57cec5SDimitry Andric       CmdArgs.push_back("--fix-cortex-a53-843419");
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric 
415d65cd7a5SDimitry Andric   ToolChain.addExtraOpts(CmdArgs);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   CmdArgs.push_back("--eh-frame-hdr");
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
4200b57cec5SDimitry Andric     CmdArgs.push_back("-m");
4210b57cec5SDimitry Andric     CmdArgs.push_back(LDMOption);
4220b57cec5SDimitry Andric   } else {
4230b57cec5SDimitry Andric     D.Diag(diag::err_target_unknown_triple) << Triple.str();
4240b57cec5SDimitry Andric     return;
4250b57cec5SDimitry Andric   }
4260fca6ea1SDimitry Andric 
4270fca6ea1SDimitry Andric   if (Triple.isRISCV()) {
42881ad6265SDimitry Andric     CmdArgs.push_back("-X");
4290fca6ea1SDimitry Andric     if (Args.hasArg(options::OPT_mno_relax))
4300fca6ea1SDimitry Andric       CmdArgs.push_back("--no-relax");
4310fca6ea1SDimitry Andric   }
4320b57cec5SDimitry Andric 
4335f757f3fSDimitry Andric   const bool IsShared = Args.hasArg(options::OPT_shared);
4345f757f3fSDimitry Andric   if (IsShared)
4350b57cec5SDimitry Andric     CmdArgs.push_back("-shared");
4365f757f3fSDimitry Andric   bool IsPIE = false;
4375f757f3fSDimitry Andric   if (IsStaticPIE) {
438349cc55cSDimitry Andric     CmdArgs.push_back("-static");
4395f757f3fSDimitry Andric     CmdArgs.push_back("-pie");
4405f757f3fSDimitry Andric     CmdArgs.push_back("--no-dynamic-linker");
4415f757f3fSDimitry Andric     CmdArgs.push_back("-z");
4425f757f3fSDimitry Andric     CmdArgs.push_back("text");
4435f757f3fSDimitry Andric   } else if (IsStatic) {
4445f757f3fSDimitry Andric     CmdArgs.push_back("-static");
4455f757f3fSDimitry Andric   } else if (!Args.hasArg(options::OPT_r)) {
4460b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_rdynamic))
4470b57cec5SDimitry Andric       CmdArgs.push_back("-export-dynamic");
4485f757f3fSDimitry Andric     if (!IsShared) {
4495f757f3fSDimitry Andric       IsPIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie,
4505f757f3fSDimitry Andric                            ToolChain.isPIEDefault(Args));
4515f757f3fSDimitry Andric       if (IsPIE)
4525f757f3fSDimitry Andric         CmdArgs.push_back("-pie");
4530b57cec5SDimitry Andric       CmdArgs.push_back("-dynamic-linker");
4545ffd83dbSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
4555ffd83dbSDimitry Andric                                            ToolChain.getDynamicLinker(Args)));
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   CmdArgs.push_back("-o");
4600b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
4610b57cec5SDimitry Andric 
46204eeddc0SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
46304eeddc0SDimitry Andric                    options::OPT_r)) {
4640b57cec5SDimitry Andric     if (!isAndroid && !IsIAMCU) {
4650b57cec5SDimitry Andric       const char *crt1 = nullptr;
4660b57cec5SDimitry Andric       if (!Args.hasArg(options::OPT_shared)) {
4670b57cec5SDimitry Andric         if (Args.hasArg(options::OPT_pg))
4680b57cec5SDimitry Andric           crt1 = "gcrt1.o";
4690b57cec5SDimitry Andric         else if (IsPIE)
4700b57cec5SDimitry Andric           crt1 = "Scrt1.o";
4710b57cec5SDimitry Andric         else if (IsStaticPIE)
4720b57cec5SDimitry Andric           crt1 = "rcrt1.o";
4730b57cec5SDimitry Andric         else
4740b57cec5SDimitry Andric           crt1 = "crt1.o";
4750b57cec5SDimitry Andric       }
4760b57cec5SDimitry Andric       if (crt1)
4770b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
4800b57cec5SDimitry Andric     }
4810b57cec5SDimitry Andric 
4825ffd83dbSDimitry Andric     if (IsVE) {
4835ffd83dbSDimitry Andric       CmdArgs.push_back("-z");
4845ffd83dbSDimitry Andric       CmdArgs.push_back("max-page-size=0x4000000");
4855ffd83dbSDimitry Andric     }
4865ffd83dbSDimitry Andric 
4870b57cec5SDimitry Andric     if (IsIAMCU)
4880b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
4890b57cec5SDimitry Andric     else if (HasCRTBeginEndFiles) {
4900b57cec5SDimitry Andric       std::string P;
4910b57cec5SDimitry Andric       if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&
4920b57cec5SDimitry Andric           !isAndroid) {
4930b57cec5SDimitry Andric         std::string crtbegin = ToolChain.getCompilerRT(Args, "crtbegin",
4940b57cec5SDimitry Andric                                                        ToolChain::FT_Object);
4950b57cec5SDimitry Andric         if (ToolChain.getVFS().exists(crtbegin))
4960b57cec5SDimitry Andric           P = crtbegin;
4970b57cec5SDimitry Andric       }
4980b57cec5SDimitry Andric       if (P.empty()) {
4990b57cec5SDimitry Andric         const char *crtbegin;
500349cc55cSDimitry Andric         if (Args.hasArg(options::OPT_shared))
5010b57cec5SDimitry Andric           crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
502349cc55cSDimitry Andric         else if (IsStatic)
503349cc55cSDimitry Andric           crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
5040b57cec5SDimitry Andric         else if (IsPIE || IsStaticPIE)
5050b57cec5SDimitry Andric           crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
5060b57cec5SDimitry Andric         else
5070b57cec5SDimitry Andric           crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
5080b57cec5SDimitry Andric         P = ToolChain.GetFilePath(crtbegin);
5090b57cec5SDimitry Andric       }
5100b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(P));
5110b57cec5SDimitry Andric     }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric     // Add crtfastmath.o if available and fast math is enabled.
5145ffd83dbSDimitry Andric     ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
5157a6dacacSDimitry Andric 
5167a6dacacSDimitry Andric     if (isAndroid && Args.hasFlag(options::OPT_fandroid_pad_segment,
5177a6dacacSDimitry Andric                                   options::OPT_fno_android_pad_segment, false))
5187a6dacacSDimitry Andric       CmdArgs.push_back(
5197a6dacacSDimitry Andric           Args.MakeArgString(ToolChain.GetFilePath("crt_pad_segment.o")));
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric 
5225f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   if (D.isUsingLTO()) {
5270b57cec5SDimitry Andric     assert(!Inputs.empty() && "Must have at least one input.");
5285f757f3fSDimitry Andric     // Find the first filename InputInfo object.
5295f757f3fSDimitry Andric     auto Input = llvm::find_if(
5305f757f3fSDimitry Andric         Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
5315f757f3fSDimitry Andric     if (Input == Inputs.end())
5325f757f3fSDimitry Andric       // For a very rare case, all of the inputs to the linker are
5335f757f3fSDimitry Andric       // InputArg. If that happens, just use the first InputInfo.
5345f757f3fSDimitry Andric       Input = Inputs.begin();
5355f757f3fSDimitry Andric 
5365f757f3fSDimitry Andric     addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
5370b57cec5SDimitry Andric                   D.getLTOMode() == LTOK_Thin);
5380b57cec5SDimitry Andric   }
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
5410b57cec5SDimitry Andric     CmdArgs.push_back("--no-demangle");
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
5440b57cec5SDimitry Andric   bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
54519587d74SEd Maste   addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
5460b57cec5SDimitry Andric   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
54781ad6265SDimitry Andric 
5485f757f3fSDimitry Andric   addHIPRuntimeLibArgs(ToolChain, C, Args, CmdArgs);
54981ad6265SDimitry Andric 
5500b57cec5SDimitry Andric   // The profile runtime also needs access to system libraries.
5510b57cec5SDimitry Andric   getToolChain().addProfileRTLibs(Args, CmdArgs);
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   if (D.CCCIsCXX() &&
55404eeddc0SDimitry Andric       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
55504eeddc0SDimitry Andric                    options::OPT_r)) {
5560b57cec5SDimitry Andric     if (ToolChain.ShouldLinkCXXStdlib(Args)) {
5570b57cec5SDimitry Andric       bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
5580b57cec5SDimitry Andric                                  !Args.hasArg(options::OPT_static);
5590b57cec5SDimitry Andric       if (OnlyLibstdcxxStatic)
5600b57cec5SDimitry Andric         CmdArgs.push_back("-Bstatic");
5610b57cec5SDimitry Andric       ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
5620b57cec5SDimitry Andric       if (OnlyLibstdcxxStatic)
5630b57cec5SDimitry Andric         CmdArgs.push_back("-Bdynamic");
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric     CmdArgs.push_back("-lm");
5660b57cec5SDimitry Andric   }
56781ad6265SDimitry Andric 
5680b57cec5SDimitry Andric   // Silence warnings when linking C code with a C++ '-stdlib' argument.
5690b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
5700b57cec5SDimitry Andric 
57181ad6265SDimitry Andric   // Additional linker set-up and flags for Fortran. This is required in order
57281ad6265SDimitry Andric   // to generate executables. As Fortran runtime depends on the C runtime,
57381ad6265SDimitry Andric   // these dependencies need to be listed before the C runtime below (i.e.
5745f757f3fSDimitry Andric   // AddRunTimeLibs).
57581ad6265SDimitry Andric   if (D.IsFlangMode()) {
57681ad6265SDimitry Andric     addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
5775f757f3fSDimitry Andric     addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
57881ad6265SDimitry Andric     CmdArgs.push_back("-lm");
57981ad6265SDimitry Andric   }
58081ad6265SDimitry Andric 
58104eeddc0SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
5820b57cec5SDimitry Andric     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
5830b57cec5SDimitry Andric       if (IsStatic || IsStaticPIE)
5840b57cec5SDimitry Andric         CmdArgs.push_back("--start-group");
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric       if (NeedsSanitizerDeps)
5875f757f3fSDimitry Andric         linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric       if (NeedsXRayDeps)
5905f757f3fSDimitry Andric         linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric       bool WantPthread = Args.hasArg(options::OPT_pthread) ||
5930b57cec5SDimitry Andric                          Args.hasArg(options::OPT_pthreads);
5940b57cec5SDimitry Andric 
595a7dea167SDimitry Andric       // Use the static OpenMP runtime with -static-openmp
596a7dea167SDimitry Andric       bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
597a7dea167SDimitry Andric                           !Args.hasArg(options::OPT_static);
598a7dea167SDimitry Andric 
5990b57cec5SDimitry Andric       // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
6000b57cec5SDimitry Andric       // require librt. Most modern Linux platforms do, but some may not.
6010fca6ea1SDimitry Andric       if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP,
6020b57cec5SDimitry Andric                            JA.isHostOffloading(Action::OFK_OpenMP),
6030b57cec5SDimitry Andric                            /* GompNeedsRT= */ true))
6040b57cec5SDimitry Andric         // OpenMP runtimes implies pthreads when using the GNU toolchain.
6050b57cec5SDimitry Andric         // FIXME: Does this really make sense for all GNU toolchains?
6060b57cec5SDimitry Andric         WantPthread = true;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric       AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
6090b57cec5SDimitry Andric 
61061cfbce3SDimitry Andric       // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
61161cfbce3SDimitry Andric       // forcibly link with libatomic as a workaround.
61261cfbce3SDimitry Andric       // TODO: Issue #41880 and D118021.
61361cfbce3SDimitry Andric       if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
61461cfbce3SDimitry Andric         CmdArgs.push_back("--push-state");
61561cfbce3SDimitry Andric         CmdArgs.push_back("--as-needed");
61661cfbce3SDimitry Andric         CmdArgs.push_back("-latomic");
61761cfbce3SDimitry Andric         CmdArgs.push_back("--pop-state");
61861cfbce3SDimitry Andric       }
61961cfbce3SDimitry Andric 
62006c3fb27SDimitry Andric       // We don't need libpthread neither for bionic (Android) nor for musl,
62106c3fb27SDimitry Andric       // (used by OHOS as runtime library).
62206c3fb27SDimitry Andric       if (WantPthread && !isAndroid && !isOHOSFamily)
6230b57cec5SDimitry Andric         CmdArgs.push_back("-lpthread");
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric       if (Args.hasArg(options::OPT_fsplit_stack))
6260b57cec5SDimitry Andric         CmdArgs.push_back("--wrap=pthread_create");
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric       if (!Args.hasArg(options::OPT_nolibc))
6290b57cec5SDimitry Andric         CmdArgs.push_back("-lc");
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric       // Add IAMCU specific libs, if needed.
6320b57cec5SDimitry Andric       if (IsIAMCU)
6330b57cec5SDimitry Andric         CmdArgs.push_back("-lgloss");
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric       if (IsStatic || IsStaticPIE)
6360b57cec5SDimitry Andric         CmdArgs.push_back("--end-group");
6370b57cec5SDimitry Andric       else
6380b57cec5SDimitry Andric         AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric       // Add IAMCU specific libs (outside the group), if needed.
6410b57cec5SDimitry Andric       if (IsIAMCU) {
6420b57cec5SDimitry Andric         CmdArgs.push_back("--as-needed");
6430b57cec5SDimitry Andric         CmdArgs.push_back("-lsoftfp");
6440b57cec5SDimitry Andric         CmdArgs.push_back("--no-as-needed");
6450b57cec5SDimitry Andric       }
6460b57cec5SDimitry Andric     }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) {
6490b57cec5SDimitry Andric       if (HasCRTBeginEndFiles) {
6500b57cec5SDimitry Andric         std::string P;
6510b57cec5SDimitry Andric         if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&
6520b57cec5SDimitry Andric             !isAndroid) {
6530b57cec5SDimitry Andric           std::string crtend = ToolChain.getCompilerRT(Args, "crtend",
6540b57cec5SDimitry Andric                                                        ToolChain::FT_Object);
6550b57cec5SDimitry Andric           if (ToolChain.getVFS().exists(crtend))
6560b57cec5SDimitry Andric             P = crtend;
6570b57cec5SDimitry Andric         }
6580b57cec5SDimitry Andric         if (P.empty()) {
6590b57cec5SDimitry Andric           const char *crtend;
6600b57cec5SDimitry Andric           if (Args.hasArg(options::OPT_shared))
6610b57cec5SDimitry Andric             crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
6620b57cec5SDimitry Andric           else if (IsPIE || IsStaticPIE)
6630b57cec5SDimitry Andric             crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
6640b57cec5SDimitry Andric           else
6650b57cec5SDimitry Andric             crtend = isAndroid ? "crtend_android.o" : "crtend.o";
6660b57cec5SDimitry Andric           P = ToolChain.GetFilePath(crtend);
6670b57cec5SDimitry Andric         }
6680b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(P));
6690b57cec5SDimitry Andric       }
6700b57cec5SDimitry Andric       if (!isAndroid)
6710b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
6720b57cec5SDimitry Andric     }
6730b57cec5SDimitry Andric   }
6740b57cec5SDimitry Andric 
6755ffd83dbSDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_T);
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
678e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
679e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
680e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric void tools::gnutools::Assembler::ConstructJob(Compilation &C,
6840b57cec5SDimitry Andric                                               const JobAction &JA,
6850b57cec5SDimitry Andric                                               const InputInfo &Output,
6860b57cec5SDimitry Andric                                               const InputInfoList &Inputs,
6870b57cec5SDimitry Andric                                               const ArgList &Args,
6880b57cec5SDimitry Andric                                               const char *LinkingOutput) const {
6890b57cec5SDimitry Andric   const auto &D = getToolChain().getDriver();
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   claimNoWarnArgs(Args);
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   ArgStringList CmdArgs;
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   llvm::Reloc::Model RelocationModel;
6960b57cec5SDimitry Andric   unsigned PICLevel;
6970b57cec5SDimitry Andric   bool IsPIE;
6985ffd83dbSDimitry Andric   const char *DefaultAssembler = "as";
6995f757f3fSDimitry Andric   // Enforce GNU as on Solaris; the native assembler's input syntax isn't fully
7005f757f3fSDimitry Andric   // compatible.
7015f757f3fSDimitry Andric   if (getToolChain().getTriple().isOSSolaris())
7025f757f3fSDimitry Andric     DefaultAssembler = "gas";
7030b57cec5SDimitry Andric   std::tie(RelocationModel, PICLevel, IsPIE) =
7040b57cec5SDimitry Andric       ParsePICArgs(getToolChain(), Args);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ)) {
7070b57cec5SDimitry Andric     if (A->getOption().getID() == options::OPT_gz) {
7080b57cec5SDimitry Andric       CmdArgs.push_back("--compress-debug-sections");
7090b57cec5SDimitry Andric     } else {
7100b57cec5SDimitry Andric       StringRef Value = A->getValue();
711bdd1243dSDimitry Andric       if (Value == "none" || Value == "zlib" || Value == "zstd") {
7120b57cec5SDimitry Andric         CmdArgs.push_back(
7130b57cec5SDimitry Andric             Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
7140b57cec5SDimitry Andric       } else {
7150b57cec5SDimitry Andric         D.Diag(diag::err_drv_unsupported_option_argument)
716bdd1243dSDimitry Andric             << A->getSpelling() << Value;
7170b57cec5SDimitry Andric       }
7180b57cec5SDimitry Andric     }
7190b57cec5SDimitry Andric   }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   switch (getToolChain().getArch()) {
7220b57cec5SDimitry Andric   default:
7230b57cec5SDimitry Andric     break;
7240b57cec5SDimitry Andric   // Add --32/--64 to make sure we get the format we want.
7250b57cec5SDimitry Andric   // This is incomplete
7260b57cec5SDimitry Andric   case llvm::Triple::x86:
7270b57cec5SDimitry Andric     CmdArgs.push_back("--32");
7280b57cec5SDimitry Andric     break;
7290b57cec5SDimitry Andric   case llvm::Triple::x86_64:
730fe6060f1SDimitry Andric     if (getToolChain().getTriple().isX32())
7310b57cec5SDimitry Andric       CmdArgs.push_back("--x32");
7320b57cec5SDimitry Andric     else
7330b57cec5SDimitry Andric       CmdArgs.push_back("--64");
7340b57cec5SDimitry Andric     break;
7350b57cec5SDimitry Andric   case llvm::Triple::ppc: {
7360b57cec5SDimitry Andric     CmdArgs.push_back("-a32");
7370b57cec5SDimitry Andric     CmdArgs.push_back("-mppc");
738e8d8bef9SDimitry Andric     CmdArgs.push_back("-mbig-endian");
739349cc55cSDimitry Andric     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
740349cc55cSDimitry Andric         getCPUName(D, Args, getToolChain().getTriple())));
741e8d8bef9SDimitry Andric     break;
742e8d8bef9SDimitry Andric   }
743e8d8bef9SDimitry Andric   case llvm::Triple::ppcle: {
744e8d8bef9SDimitry Andric     CmdArgs.push_back("-a32");
745e8d8bef9SDimitry Andric     CmdArgs.push_back("-mppc");
746e8d8bef9SDimitry Andric     CmdArgs.push_back("-mlittle-endian");
747349cc55cSDimitry Andric     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
748349cc55cSDimitry Andric         getCPUName(D, Args, getToolChain().getTriple())));
7490b57cec5SDimitry Andric     break;
7500b57cec5SDimitry Andric   }
7510b57cec5SDimitry Andric   case llvm::Triple::ppc64: {
7520b57cec5SDimitry Andric     CmdArgs.push_back("-a64");
7530b57cec5SDimitry Andric     CmdArgs.push_back("-mppc64");
754e8d8bef9SDimitry Andric     CmdArgs.push_back("-mbig-endian");
755349cc55cSDimitry Andric     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
756349cc55cSDimitry Andric         getCPUName(D, Args, getToolChain().getTriple())));
7570b57cec5SDimitry Andric     break;
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric   case llvm::Triple::ppc64le: {
7600b57cec5SDimitry Andric     CmdArgs.push_back("-a64");
7610b57cec5SDimitry Andric     CmdArgs.push_back("-mppc64");
7620b57cec5SDimitry Andric     CmdArgs.push_back("-mlittle-endian");
763349cc55cSDimitry Andric     CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
764349cc55cSDimitry Andric         getCPUName(D, Args, getToolChain().getTriple())));
7650b57cec5SDimitry Andric     break;
7660b57cec5SDimitry Andric   }
7670b57cec5SDimitry Andric   case llvm::Triple::riscv32:
7680b57cec5SDimitry Andric   case llvm::Triple::riscv64: {
7690b57cec5SDimitry Andric     StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
7700b57cec5SDimitry Andric     CmdArgs.push_back("-mabi");
7710b57cec5SDimitry Andric     CmdArgs.push_back(ABIName.data());
7720fca6ea1SDimitry Andric     std::string MArchName =
7730fca6ea1SDimitry Andric         riscv::getRISCVArch(Args, getToolChain().getTriple());
7740b57cec5SDimitry Andric     CmdArgs.push_back("-march");
7750fca6ea1SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(MArchName));
77681ad6265SDimitry Andric     if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
77781ad6265SDimitry Andric       Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);
7780b57cec5SDimitry Andric     break;
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric   case llvm::Triple::sparc:
7810b57cec5SDimitry Andric   case llvm::Triple::sparcel: {
7820b57cec5SDimitry Andric     CmdArgs.push_back("-32");
783349cc55cSDimitry Andric     std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
7840b57cec5SDimitry Andric     CmdArgs.push_back(
7850b57cec5SDimitry Andric         sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
7860b57cec5SDimitry Andric     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
7870b57cec5SDimitry Andric     break;
7880b57cec5SDimitry Andric   }
7890b57cec5SDimitry Andric   case llvm::Triple::sparcv9: {
7900b57cec5SDimitry Andric     CmdArgs.push_back("-64");
791349cc55cSDimitry Andric     std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
7920b57cec5SDimitry Andric     CmdArgs.push_back(
7930b57cec5SDimitry Andric         sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
7940b57cec5SDimitry Andric     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
7950b57cec5SDimitry Andric     break;
7960b57cec5SDimitry Andric   }
7970b57cec5SDimitry Andric   case llvm::Triple::arm:
7980b57cec5SDimitry Andric   case llvm::Triple::armeb:
7990b57cec5SDimitry Andric   case llvm::Triple::thumb:
8000b57cec5SDimitry Andric   case llvm::Triple::thumbeb: {
8010b57cec5SDimitry Andric     const llvm::Triple &Triple2 = getToolChain().getTriple();
80206c3fb27SDimitry Andric     CmdArgs.push_back(arm::isARMBigEndian(Triple2, Args) ? "-EB" : "-EL");
8030b57cec5SDimitry Andric     switch (Triple2.getSubArch()) {
8040b57cec5SDimitry Andric     case llvm::Triple::ARMSubArch_v7:
8050b57cec5SDimitry Andric       CmdArgs.push_back("-mfpu=neon");
8060b57cec5SDimitry Andric       break;
8070b57cec5SDimitry Andric     case llvm::Triple::ARMSubArch_v8:
8080b57cec5SDimitry Andric       CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
8090b57cec5SDimitry Andric       break;
8100b57cec5SDimitry Andric     default:
8110b57cec5SDimitry Andric       break;
8120b57cec5SDimitry Andric     }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric     switch (arm::getARMFloatABI(getToolChain(), Args)) {
8150b57cec5SDimitry Andric     case arm::FloatABI::Invalid: llvm_unreachable("must have an ABI!");
8160b57cec5SDimitry Andric     case arm::FloatABI::Soft:
8170b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=soft"));
8180b57cec5SDimitry Andric       break;
8190b57cec5SDimitry Andric     case arm::FloatABI::SoftFP:
8200b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=softfp"));
8210b57cec5SDimitry Andric       break;
8220b57cec5SDimitry Andric     case arm::FloatABI::Hard:
8230b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=hard"));
8240b57cec5SDimitry Andric       break;
8250b57cec5SDimitry Andric     }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
8280b57cec5SDimitry Andric     normalizeCPUNamesForAssembler(Args, CmdArgs);
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
83106c3fb27SDimitry Andric     // The integrated assembler doesn't implement e_flags setting behavior for
83206c3fb27SDimitry Andric     // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For
83306c3fb27SDimitry Andric     // compatibility we accept but warn.
83406c3fb27SDimitry Andric     if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
83506c3fb27SDimitry Andric       A->ignoreTargetSpecific();
8360b57cec5SDimitry Andric     break;
8370b57cec5SDimitry Andric   }
8380b57cec5SDimitry Andric   case llvm::Triple::aarch64:
8390b57cec5SDimitry Andric   case llvm::Triple::aarch64_be: {
8400b57cec5SDimitry Andric     CmdArgs.push_back(
8410b57cec5SDimitry Andric         getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL");
8420b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
8430b57cec5SDimitry Andric     normalizeCPUNamesForAssembler(Args, CmdArgs);
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric     break;
8460b57cec5SDimitry Andric   }
84706c3fb27SDimitry Andric   // TODO: handle loongarch32.
84806c3fb27SDimitry Andric   case llvm::Triple::loongarch64: {
84906c3fb27SDimitry Andric     StringRef ABIName =
85006c3fb27SDimitry Andric         loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());
85106c3fb27SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));
85206c3fb27SDimitry Andric     break;
85306c3fb27SDimitry Andric   }
8540b57cec5SDimitry Andric   case llvm::Triple::mips:
8550b57cec5SDimitry Andric   case llvm::Triple::mipsel:
8560b57cec5SDimitry Andric   case llvm::Triple::mips64:
8570b57cec5SDimitry Andric   case llvm::Triple::mips64el: {
8580b57cec5SDimitry Andric     StringRef CPUName;
8590b57cec5SDimitry Andric     StringRef ABIName;
8600b57cec5SDimitry Andric     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
8610b57cec5SDimitry Andric     ABIName = mips::getGnuCompatibleMipsABIName(ABIName);
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric     CmdArgs.push_back("-march");
8640b57cec5SDimitry Andric     CmdArgs.push_back(CPUName.data());
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric     CmdArgs.push_back("-mabi");
8670b57cec5SDimitry Andric     CmdArgs.push_back(ABIName.data());
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric     // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
8700b57cec5SDimitry Andric     // or -mshared (not implemented) is in effect.
8710b57cec5SDimitry Andric     if (RelocationModel == llvm::Reloc::Static)
8720b57cec5SDimitry Andric       CmdArgs.push_back("-mno-shared");
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric     // LLVM doesn't support -mplt yet and acts as if it is always given.
8750b57cec5SDimitry Andric     // However, -mplt has no effect with the N64 ABI.
8760b57cec5SDimitry Andric     if (ABIName != "64" && !Args.hasArg(options::OPT_mno_abicalls))
8770b57cec5SDimitry Andric       CmdArgs.push_back("-call_nonpic");
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     if (getToolChain().getTriple().isLittleEndian())
8800b57cec5SDimitry Andric       CmdArgs.push_back("-EL");
8810b57cec5SDimitry Andric     else
8820b57cec5SDimitry Andric       CmdArgs.push_back("-EB");
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
8850b57cec5SDimitry Andric       if (StringRef(A->getValue()) == "2008")
8860b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
8870b57cec5SDimitry Andric     }
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric     // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
8900b57cec5SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
8910b57cec5SDimitry Andric                                  options::OPT_mfp64)) {
8920b57cec5SDimitry Andric       A->claim();
8930b57cec5SDimitry Andric       A->render(Args, CmdArgs);
8940b57cec5SDimitry Andric     } else if (mips::shouldUseFPXX(
8950b57cec5SDimitry Andric                    Args, getToolChain().getTriple(), CPUName, ABIName,
8960b57cec5SDimitry Andric                    mips::getMipsFloatABI(getToolChain().getDriver(), Args,
8970b57cec5SDimitry Andric                                          getToolChain().getTriple())))
8980b57cec5SDimitry Andric       CmdArgs.push_back("-mfpxx");
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric     // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
9010b57cec5SDimitry Andric     // -mno-mips16 is actually -no-mips16.
9020b57cec5SDimitry Andric     if (Arg *A =
9030b57cec5SDimitry Andric             Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16)) {
9040b57cec5SDimitry Andric       if (A->getOption().matches(options::OPT_mips16)) {
9050b57cec5SDimitry Andric         A->claim();
9060b57cec5SDimitry Andric         A->render(Args, CmdArgs);
9070b57cec5SDimitry Andric       } else {
9080b57cec5SDimitry Andric         A->claim();
9090b57cec5SDimitry Andric         CmdArgs.push_back("-no-mips16");
9100b57cec5SDimitry Andric       }
9110b57cec5SDimitry Andric     }
9120b57cec5SDimitry Andric 
9130b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
9140b57cec5SDimitry Andric                     options::OPT_mno_micromips);
9150b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
9160b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
9190b57cec5SDimitry Andric       // Do not use AddLastArg because not all versions of MIPS assembler
9200b57cec5SDimitry Andric       // support -mmsa / -mno-msa options.
9210b57cec5SDimitry Andric       if (A->getOption().matches(options::OPT_mmsa))
9220b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString("-mmsa"));
9230b57cec5SDimitry Andric     }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
9260b57cec5SDimitry Andric                     options::OPT_msoft_float);
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,
9290b57cec5SDimitry Andric                     options::OPT_msingle_float);
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
9320b57cec5SDimitry Andric                     options::OPT_mno_odd_spreg);
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
9350b57cec5SDimitry Andric     break;
9360b57cec5SDimitry Andric   }
9370b57cec5SDimitry Andric   case llvm::Triple::systemz: {
9380b57cec5SDimitry Andric     // Always pass an -march option, since our default of z10 is later
9390b57cec5SDimitry Andric     // than the GNU assembler's default.
940480093f4SDimitry Andric     std::string CPUName = systemz::getSystemZTargetCPU(Args);
9410b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
9420b57cec5SDimitry Andric     break;
9430b57cec5SDimitry Andric   }
9445ffd83dbSDimitry Andric   case llvm::Triple::ve:
9455ffd83dbSDimitry Andric     DefaultAssembler = "nas";
9460b57cec5SDimitry Andric   }
9470b57cec5SDimitry Andric 
948480093f4SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
949480093f4SDimitry Andric                                     options::OPT_fdebug_prefix_map_EQ)) {
950480093f4SDimitry Andric     StringRef Map = A->getValue();
951349cc55cSDimitry Andric     if (!Map.contains('='))
952480093f4SDimitry Andric       D.Diag(diag::err_drv_invalid_argument_to_option)
953480093f4SDimitry Andric           << Map << A->getOption().getName();
954480093f4SDimitry Andric     else {
955480093f4SDimitry Andric       CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));
956480093f4SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Map));
957480093f4SDimitry Andric     }
958480093f4SDimitry Andric     A->claim();
959480093f4SDimitry Andric   }
960480093f4SDimitry Andric 
9610b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_I);
9620b57cec5SDimitry Andric   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   CmdArgs.push_back("-o");
9650b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric   for (const auto &II : Inputs)
9680b57cec5SDimitry Andric     CmdArgs.push_back(II.getFilename());
9690b57cec5SDimitry Andric 
970bdd1243dSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group,
971bdd1243dSDimitry Andric                                options::OPT_gdwarf_2, options::OPT_gdwarf_3,
972bdd1243dSDimitry Andric                                options::OPT_gdwarf_4, options::OPT_gdwarf_5,
973bdd1243dSDimitry Andric                                options::OPT_gdwarf))
974bdd1243dSDimitry Andric     if (!A->getOption().matches(options::OPT_g0)) {
975bdd1243dSDimitry Andric       Args.AddLastArg(CmdArgs, options::OPT_g_Flag);
976bdd1243dSDimitry Andric 
977bdd1243dSDimitry Andric       unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
978bdd1243dSDimitry Andric       CmdArgs.push_back(Args.MakeArgString("-gdwarf-" + Twine(DwarfVersion)));
979bdd1243dSDimitry Andric     }
980bdd1243dSDimitry Andric 
9815ffd83dbSDimitry Andric   const char *Exec =
9825ffd83dbSDimitry Andric       Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));
983e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
984e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
985e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   // Handle the debug info splitting at object creation time if we're
9880b57cec5SDimitry Andric   // creating an object.
9890b57cec5SDimitry Andric   // TODO: Currently only works on linux with newer objcopy.
9900b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_gsplit_dwarf) &&
9910b57cec5SDimitry Andric       getToolChain().getTriple().isOSLinux())
9920b57cec5SDimitry Andric     SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
993e8d8bef9SDimitry Andric                    SplitDebugName(JA, Args, Inputs[0], Output));
9940b57cec5SDimitry Andric }
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric namespace {
9970b57cec5SDimitry Andric // Filter to remove Multilibs that don't exist as a suffix to Path
9980b57cec5SDimitry Andric class FilterNonExistent {
9990b57cec5SDimitry Andric   StringRef Base, File;
10000b57cec5SDimitry Andric   llvm::vfs::FileSystem &VFS;
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric public:
10030b57cec5SDimitry Andric   FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)
10040b57cec5SDimitry Andric       : Base(Base), File(File), VFS(VFS) {}
10050b57cec5SDimitry Andric   bool operator()(const Multilib &M) {
10060b57cec5SDimitry Andric     return !VFS.exists(Base + M.gccSuffix() + File);
10070b57cec5SDimitry Andric   }
10080b57cec5SDimitry Andric };
10090b57cec5SDimitry Andric } // end anonymous namespace
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric static bool isSoftFloatABI(const ArgList &Args) {
10120b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
10130b57cec5SDimitry Andric                            options::OPT_mfloat_abi_EQ);
10140b57cec5SDimitry Andric   if (!A)
10150b57cec5SDimitry Andric     return false;
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   return A->getOption().matches(options::OPT_msoft_float) ||
10180b57cec5SDimitry Andric          (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
10190b57cec5SDimitry Andric           A->getValue() == StringRef("soft"));
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {
10230b57cec5SDimitry Andric   return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric static bool isMipsEL(llvm::Triple::ArchType Arch) {
10270b57cec5SDimitry Andric   return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
10280b57cec5SDimitry Andric }
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric static bool isMips16(const ArgList &Args) {
10310b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
10320b57cec5SDimitry Andric   return A && A->getOption().matches(options::OPT_mips16);
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric static bool isMicroMips(const ArgList &Args) {
10360b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
10370b57cec5SDimitry Andric   return A && A->getOption().matches(options::OPT_mmicromips);
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric static bool isMSP430(llvm::Triple::ArchType Arch) {
10410b57cec5SDimitry Andric   return Arch == llvm::Triple::msp430;
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
10450b57cec5SDimitry Andric                                 FilterNonExistent &NonExistent,
10460b57cec5SDimitry Andric                                 DetectedMultilibs &Result) {
10470b57cec5SDimitry Andric   // Check for Code Sourcery toolchain multilibs
10480b57cec5SDimitry Andric   MultilibSet CSMipsMultilibs;
10490b57cec5SDimitry Andric   {
105006c3fb27SDimitry Andric     auto MArchMips16 = MultilibBuilder("/mips16").flag("-m32").flag("-mips16");
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric     auto MArchMicroMips =
105306c3fb27SDimitry Andric         MultilibBuilder("/micromips").flag("-m32").flag("-mmicromips");
10540b57cec5SDimitry Andric 
105506c3fb27SDimitry Andric     auto MArchDefault = MultilibBuilder("")
105606c3fb27SDimitry Andric                             .flag("-mips16", /*Disallow=*/true)
105706c3fb27SDimitry Andric                             .flag("-mmicromips", /*Disallow=*/true);
10580b57cec5SDimitry Andric 
105906c3fb27SDimitry Andric     auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
10600b57cec5SDimitry Andric 
106106c3fb27SDimitry Andric     auto SoftFloat = MultilibBuilder("/soft-float").flag("-msoft-float");
10620b57cec5SDimitry Andric 
106306c3fb27SDimitry Andric     auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
10640b57cec5SDimitry Andric 
106506c3fb27SDimitry Andric     auto DefaultFloat = MultilibBuilder("")
106606c3fb27SDimitry Andric                             .flag("-msoft-float", /*Disallow=*/true)
106706c3fb27SDimitry Andric                             .flag("-mnan=2008", /*Disallow=*/true);
10680b57cec5SDimitry Andric 
106906c3fb27SDimitry Andric     auto BigEndian =
107006c3fb27SDimitry Andric         MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
10710b57cec5SDimitry Andric 
107206c3fb27SDimitry Andric     auto LittleEndian =
107306c3fb27SDimitry Andric         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric     // Note that this one's osSuffix is ""
107606c3fb27SDimitry Andric     auto MAbi64 = MultilibBuilder("")
10770b57cec5SDimitry Andric                       .gccSuffix("/64")
10780b57cec5SDimitry Andric                       .includeSuffix("/64")
107906c3fb27SDimitry Andric                       .flag("-mabi=n64")
108006c3fb27SDimitry Andric                       .flag("-mabi=n32", /*Disallow=*/true)
108106c3fb27SDimitry Andric                       .flag("-m32", /*Disallow=*/true);
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric     CSMipsMultilibs =
108406c3fb27SDimitry Andric         MultilibSetBuilder()
10850b57cec5SDimitry Andric             .Either(MArchMips16, MArchMicroMips, MArchDefault)
10860b57cec5SDimitry Andric             .Maybe(UCLibc)
10870b57cec5SDimitry Andric             .Either(SoftFloat, Nan2008, DefaultFloat)
10880b57cec5SDimitry Andric             .FilterOut("/micromips/nan2008")
10890b57cec5SDimitry Andric             .FilterOut("/mips16/nan2008")
10900b57cec5SDimitry Andric             .Either(BigEndian, LittleEndian)
10910b57cec5SDimitry Andric             .Maybe(MAbi64)
10920b57cec5SDimitry Andric             .FilterOut("/mips16.*/64")
10930b57cec5SDimitry Andric             .FilterOut("/micromips.*/64")
109406c3fb27SDimitry Andric             .makeMultilibSet()
10950b57cec5SDimitry Andric             .FilterOut(NonExistent)
10960b57cec5SDimitry Andric             .setIncludeDirsCallback([](const Multilib &M) {
10970b57cec5SDimitry Andric               std::vector<std::string> Dirs({"/include"});
10985f757f3fSDimitry Andric               if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
10990b57cec5SDimitry Andric                 Dirs.push_back(
11000b57cec5SDimitry Andric                     "/../../../../mips-linux-gnu/libc/uclibc/usr/include");
11010b57cec5SDimitry Andric               else
11020b57cec5SDimitry Andric                 Dirs.push_back("/../../../../mips-linux-gnu/libc/usr/include");
11030b57cec5SDimitry Andric               return Dirs;
11040b57cec5SDimitry Andric             });
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   MultilibSet DebianMipsMultilibs;
11080b57cec5SDimitry Andric   {
110906c3fb27SDimitry Andric     MultilibBuilder MAbiN32 =
111006c3fb27SDimitry Andric         MultilibBuilder().gccSuffix("/n32").includeSuffix("/n32").flag(
111106c3fb27SDimitry Andric             "-mabi=n32");
11120b57cec5SDimitry Andric 
111306c3fb27SDimitry Andric     MultilibBuilder M64 = MultilibBuilder()
11140b57cec5SDimitry Andric                               .gccSuffix("/64")
11150b57cec5SDimitry Andric                               .includeSuffix("/64")
111606c3fb27SDimitry Andric                               .flag("-m64")
111706c3fb27SDimitry Andric                               .flag("-m32", /*Disallow=*/true)
111806c3fb27SDimitry Andric                               .flag("-mabi=n32", /*Disallow=*/true);
111906c3fb27SDimitry Andric 
112006c3fb27SDimitry Andric     MultilibBuilder M32 = MultilibBuilder()
112106c3fb27SDimitry Andric                               .gccSuffix("/32")
112206c3fb27SDimitry Andric                               .flag("-m64", /*Disallow=*/true)
11230b57cec5SDimitry Andric                               .flag("-m32")
112406c3fb27SDimitry Andric                               .flag("-mabi=n32", /*Disallow=*/true);
11250b57cec5SDimitry Andric 
112606c3fb27SDimitry Andric     DebianMipsMultilibs = MultilibSetBuilder()
112706c3fb27SDimitry Andric                               .Either(M32, M64, MAbiN32)
112806c3fb27SDimitry Andric                               .makeMultilibSet()
112906c3fb27SDimitry Andric                               .FilterOut(NonExistent);
11300b57cec5SDimitry Andric   }
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   // Sort candidates. Toolchain that best meets the directories tree goes first.
11330b57cec5SDimitry Andric   // Then select the first toolchains matches command line flags.
11340b57cec5SDimitry Andric   MultilibSet *Candidates[] = {&CSMipsMultilibs, &DebianMipsMultilibs};
11350b57cec5SDimitry Andric   if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())
11360b57cec5SDimitry Andric     std::iter_swap(Candidates, Candidates + 1);
11370b57cec5SDimitry Andric   for (const MultilibSet *Candidate : Candidates) {
113806c3fb27SDimitry Andric     if (Candidate->select(Flags, Result.SelectedMultilibs)) {
11390b57cec5SDimitry Andric       if (Candidate == &DebianMipsMultilibs)
11400b57cec5SDimitry Andric         Result.BiarchSibling = Multilib();
11410b57cec5SDimitry Andric       Result.Multilibs = *Candidate;
11420b57cec5SDimitry Andric       return true;
11430b57cec5SDimitry Andric     }
11440b57cec5SDimitry Andric   }
11450b57cec5SDimitry Andric   return false;
11460b57cec5SDimitry Andric }
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
11490b57cec5SDimitry Andric                                      const Multilib::flags_list &Flags,
11500b57cec5SDimitry Andric                                      FilterNonExistent &NonExistent,
11510b57cec5SDimitry Andric                                      DetectedMultilibs &Result) {
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   MultilibSet AndroidMipsMultilibs =
115406c3fb27SDimitry Andric       MultilibSetBuilder()
115506c3fb27SDimitry Andric           .Maybe(MultilibBuilder("/mips-r2", {}, {}).flag("-march=mips32r2"))
115606c3fb27SDimitry Andric           .Maybe(MultilibBuilder("/mips-r6", {}, {}).flag("-march=mips32r6"))
115706c3fb27SDimitry Andric           .makeMultilibSet()
11580b57cec5SDimitry Andric           .FilterOut(NonExistent);
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   MultilibSet AndroidMipselMultilibs =
116106c3fb27SDimitry Andric       MultilibSetBuilder()
116206c3fb27SDimitry Andric           .Either(MultilibBuilder().flag("-march=mips32"),
116306c3fb27SDimitry Andric                   MultilibBuilder("/mips-r2", "", "/mips-r2")
116406c3fb27SDimitry Andric                       .flag("-march=mips32r2"),
116506c3fb27SDimitry Andric                   MultilibBuilder("/mips-r6", "", "/mips-r6")
116606c3fb27SDimitry Andric                       .flag("-march=mips32r6"))
116706c3fb27SDimitry Andric           .makeMultilibSet()
11680b57cec5SDimitry Andric           .FilterOut(NonExistent);
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric   MultilibSet AndroidMips64elMultilibs =
117106c3fb27SDimitry Andric       MultilibSetBuilder()
117206c3fb27SDimitry Andric           .Either(MultilibBuilder().flag("-march=mips64r6"),
117306c3fb27SDimitry Andric                   MultilibBuilder("/32/mips-r1", "", "/mips-r1")
117406c3fb27SDimitry Andric                       .flag("-march=mips32"),
117506c3fb27SDimitry Andric                   MultilibBuilder("/32/mips-r2", "", "/mips-r2")
117606c3fb27SDimitry Andric                       .flag("-march=mips32r2"),
117706c3fb27SDimitry Andric                   MultilibBuilder("/32/mips-r6", "", "/mips-r6")
117806c3fb27SDimitry Andric                       .flag("-march=mips32r6"))
117906c3fb27SDimitry Andric           .makeMultilibSet()
11800b57cec5SDimitry Andric           .FilterOut(NonExistent);
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric   MultilibSet *MS = &AndroidMipsMultilibs;
11830b57cec5SDimitry Andric   if (VFS.exists(Path + "/mips-r6"))
11840b57cec5SDimitry Andric     MS = &AndroidMipselMultilibs;
11850b57cec5SDimitry Andric   else if (VFS.exists(Path + "/32"))
11860b57cec5SDimitry Andric     MS = &AndroidMips64elMultilibs;
118706c3fb27SDimitry Andric   if (MS->select(Flags, Result.SelectedMultilibs)) {
11880b57cec5SDimitry Andric     Result.Multilibs = *MS;
11890b57cec5SDimitry Andric     return true;
11900b57cec5SDimitry Andric   }
11910b57cec5SDimitry Andric   return false;
11920b57cec5SDimitry Andric }
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,
11950b57cec5SDimitry Andric                                   FilterNonExistent &NonExistent,
11960b57cec5SDimitry Andric                                   DetectedMultilibs &Result) {
11970b57cec5SDimitry Andric   // Musl toolchain multilibs
11980b57cec5SDimitry Andric   MultilibSet MuslMipsMultilibs;
11990b57cec5SDimitry Andric   {
120006c3fb27SDimitry Andric     auto MArchMipsR2 = MultilibBuilder("")
12010b57cec5SDimitry Andric                            .osSuffix("/mips-r2-hard-musl")
12020b57cec5SDimitry Andric                            .flag("-EB")
120306c3fb27SDimitry Andric                            .flag("-EL", /*Disallow=*/true)
120406c3fb27SDimitry Andric                            .flag("-march=mips32r2");
12050b57cec5SDimitry Andric 
120606c3fb27SDimitry Andric     auto MArchMipselR2 = MultilibBuilder("/mipsel-r2-hard-musl")
120706c3fb27SDimitry Andric                              .flag("-EB", /*Disallow=*/true)
120806c3fb27SDimitry Andric                              .flag("-EL")
120906c3fb27SDimitry Andric                              .flag("-march=mips32r2");
121006c3fb27SDimitry Andric 
121106c3fb27SDimitry Andric     MuslMipsMultilibs = MultilibSetBuilder()
121206c3fb27SDimitry Andric                             .Either(MArchMipsR2, MArchMipselR2)
121306c3fb27SDimitry Andric                             .makeMultilibSet();
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric     // Specify the callback that computes the include directories.
12160b57cec5SDimitry Andric     MuslMipsMultilibs.setIncludeDirsCallback([](const Multilib &M) {
12170b57cec5SDimitry Andric       return std::vector<std::string>(
12180b57cec5SDimitry Andric           {"/../sysroot" + M.osSuffix() + "/usr/include"});
12190b57cec5SDimitry Andric     });
12200b57cec5SDimitry Andric   }
122106c3fb27SDimitry Andric   if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs)) {
12220b57cec5SDimitry Andric     Result.Multilibs = MuslMipsMultilibs;
12230b57cec5SDimitry Andric     return true;
12240b57cec5SDimitry Andric   }
12250b57cec5SDimitry Andric   return false;
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
12290b57cec5SDimitry Andric                                  FilterNonExistent &NonExistent,
12300b57cec5SDimitry Andric                                  DetectedMultilibs &Result) {
12310b57cec5SDimitry Andric   // CodeScape MTI toolchain v1.2 and early.
12320b57cec5SDimitry Andric   MultilibSet MtiMipsMultilibsV1;
12330b57cec5SDimitry Andric   {
123406c3fb27SDimitry Andric     auto MArchMips32 = MultilibBuilder("/mips32")
12350b57cec5SDimitry Andric                            .flag("-m32")
123606c3fb27SDimitry Andric                            .flag("-m64", /*Disallow=*/true)
123706c3fb27SDimitry Andric                            .flag("-mmicromips", /*Disallow=*/true)
123806c3fb27SDimitry Andric                            .flag("-march=mips32");
12390b57cec5SDimitry Andric 
124006c3fb27SDimitry Andric     auto MArchMicroMips = MultilibBuilder("/micromips")
124106c3fb27SDimitry Andric                               .flag("-m32")
124206c3fb27SDimitry Andric                               .flag("-m64", /*Disallow=*/true)
124306c3fb27SDimitry Andric                               .flag("-mmicromips");
12440b57cec5SDimitry Andric 
124506c3fb27SDimitry Andric     auto MArchMips64r2 = MultilibBuilder("/mips64r2")
124606c3fb27SDimitry Andric                              .flag("-m32", /*Disallow=*/true)
12470b57cec5SDimitry Andric                              .flag("-m64")
124806c3fb27SDimitry Andric                              .flag("-march=mips64r2");
12490b57cec5SDimitry Andric 
125006c3fb27SDimitry Andric     auto MArchMips64 = MultilibBuilder("/mips64")
125106c3fb27SDimitry Andric                            .flag("-m32", /*Disallow=*/true)
125206c3fb27SDimitry Andric                            .flag("-m64")
125306c3fb27SDimitry Andric                            .flag("-march=mips64r2", /*Disallow=*/true);
12540b57cec5SDimitry Andric 
125506c3fb27SDimitry Andric     auto MArchDefault = MultilibBuilder("")
125606c3fb27SDimitry Andric                             .flag("-m32")
125706c3fb27SDimitry Andric                             .flag("-m64", /*Disallow=*/true)
125806c3fb27SDimitry Andric                             .flag("-mmicromips", /*Disallow=*/true)
125906c3fb27SDimitry Andric                             .flag("-march=mips32r2");
12600b57cec5SDimitry Andric 
126106c3fb27SDimitry Andric     auto Mips16 = MultilibBuilder("/mips16").flag("-mips16");
12620b57cec5SDimitry Andric 
126306c3fb27SDimitry Andric     auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
12640b57cec5SDimitry Andric 
126506c3fb27SDimitry Andric     auto MAbi64 = MultilibBuilder("/64")
126606c3fb27SDimitry Andric                       .flag("-mabi=n64")
126706c3fb27SDimitry Andric                       .flag("-mabi=n32", /*Disallow=*/true)
126806c3fb27SDimitry Andric                       .flag("-m32", /*Disallow=*/true);
12690b57cec5SDimitry Andric 
127006c3fb27SDimitry Andric     auto BigEndian =
127106c3fb27SDimitry Andric         MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
12720b57cec5SDimitry Andric 
127306c3fb27SDimitry Andric     auto LittleEndian =
127406c3fb27SDimitry Andric         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
127506c3fb27SDimitry Andric 
127606c3fb27SDimitry Andric     auto SoftFloat = MultilibBuilder("/sof").flag("-msoft-float");
127706c3fb27SDimitry Andric 
127806c3fb27SDimitry Andric     auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric     MtiMipsMultilibsV1 =
128106c3fb27SDimitry Andric         MultilibSetBuilder()
12820b57cec5SDimitry Andric             .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64,
12830b57cec5SDimitry Andric                     MArchDefault)
12840b57cec5SDimitry Andric             .Maybe(UCLibc)
12850b57cec5SDimitry Andric             .Maybe(Mips16)
12860b57cec5SDimitry Andric             .FilterOut("/mips64/mips16")
12870b57cec5SDimitry Andric             .FilterOut("/mips64r2/mips16")
12880b57cec5SDimitry Andric             .FilterOut("/micromips/mips16")
12890b57cec5SDimitry Andric             .Maybe(MAbi64)
12900b57cec5SDimitry Andric             .FilterOut("/micromips/64")
12910b57cec5SDimitry Andric             .FilterOut("/mips32/64")
12920b57cec5SDimitry Andric             .FilterOut("^/64")
12930b57cec5SDimitry Andric             .FilterOut("/mips16/64")
12940b57cec5SDimitry Andric             .Either(BigEndian, LittleEndian)
12950b57cec5SDimitry Andric             .Maybe(SoftFloat)
12960b57cec5SDimitry Andric             .Maybe(Nan2008)
12970b57cec5SDimitry Andric             .FilterOut(".*sof/nan2008")
129806c3fb27SDimitry Andric             .makeMultilibSet()
12990b57cec5SDimitry Andric             .FilterOut(NonExistent)
13000b57cec5SDimitry Andric             .setIncludeDirsCallback([](const Multilib &M) {
13010b57cec5SDimitry Andric               std::vector<std::string> Dirs({"/include"});
13025f757f3fSDimitry Andric               if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
13030b57cec5SDimitry Andric                 Dirs.push_back("/../../../../sysroot/uclibc/usr/include");
13040b57cec5SDimitry Andric               else
13050b57cec5SDimitry Andric                 Dirs.push_back("/../../../../sysroot/usr/include");
13060b57cec5SDimitry Andric               return Dirs;
13070b57cec5SDimitry Andric             });
13080b57cec5SDimitry Andric   }
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric   // CodeScape IMG toolchain starting from v1.3.
13110b57cec5SDimitry Andric   MultilibSet MtiMipsMultilibsV2;
13120b57cec5SDimitry Andric   {
131306c3fb27SDimitry Andric     auto BeHard = MultilibBuilder("/mips-r2-hard")
131406c3fb27SDimitry Andric                       .flag("-EB")
131506c3fb27SDimitry Andric                       .flag("-msoft-float", /*Disallow=*/true)
131606c3fb27SDimitry Andric                       .flag("-mnan=2008", /*Disallow=*/true)
131706c3fb27SDimitry Andric                       .flag("-muclibc", /*Disallow=*/true);
131806c3fb27SDimitry Andric     auto BeSoft = MultilibBuilder("/mips-r2-soft")
131906c3fb27SDimitry Andric                       .flag("-EB")
13200b57cec5SDimitry Andric                       .flag("-msoft-float")
132106c3fb27SDimitry Andric                       .flag("-mnan=2008", /*Disallow=*/true);
132206c3fb27SDimitry Andric     auto ElHard = MultilibBuilder("/mipsel-r2-hard")
132306c3fb27SDimitry Andric                       .flag("-EL")
132406c3fb27SDimitry Andric                       .flag("-msoft-float", /*Disallow=*/true)
132506c3fb27SDimitry Andric                       .flag("-mnan=2008", /*Disallow=*/true)
132606c3fb27SDimitry Andric                       .flag("-muclibc", /*Disallow=*/true);
132706c3fb27SDimitry Andric     auto ElSoft = MultilibBuilder("/mipsel-r2-soft")
132806c3fb27SDimitry Andric                       .flag("-EL")
132906c3fb27SDimitry Andric                       .flag("-msoft-float")
133006c3fb27SDimitry Andric                       .flag("-mnan=2008", /*Disallow=*/true)
133106c3fb27SDimitry Andric                       .flag("-mmicromips", /*Disallow=*/true);
133206c3fb27SDimitry Andric     auto BeHardNan = MultilibBuilder("/mips-r2-hard-nan2008")
133306c3fb27SDimitry Andric                          .flag("-EB")
133406c3fb27SDimitry Andric                          .flag("-msoft-float", /*Disallow=*/true)
133506c3fb27SDimitry Andric                          .flag("-mnan=2008")
133606c3fb27SDimitry Andric                          .flag("-muclibc", /*Disallow=*/true);
133706c3fb27SDimitry Andric     auto ElHardNan = MultilibBuilder("/mipsel-r2-hard-nan2008")
133806c3fb27SDimitry Andric                          .flag("-EL")
133906c3fb27SDimitry Andric                          .flag("-msoft-float", /*Disallow=*/true)
134006c3fb27SDimitry Andric                          .flag("-mnan=2008")
134106c3fb27SDimitry Andric                          .flag("-muclibc", /*Disallow=*/true)
134206c3fb27SDimitry Andric                          .flag("-mmicromips", /*Disallow=*/true);
134306c3fb27SDimitry Andric     auto BeHardNanUclibc = MultilibBuilder("/mips-r2-hard-nan2008-uclibc")
134406c3fb27SDimitry Andric                                .flag("-EB")
134506c3fb27SDimitry Andric                                .flag("-msoft-float", /*Disallow=*/true)
13460b57cec5SDimitry Andric                                .flag("-mnan=2008")
13470b57cec5SDimitry Andric                                .flag("-muclibc");
134806c3fb27SDimitry Andric     auto ElHardNanUclibc = MultilibBuilder("/mipsel-r2-hard-nan2008-uclibc")
134906c3fb27SDimitry Andric                                .flag("-EL")
135006c3fb27SDimitry Andric                                .flag("-msoft-float", /*Disallow=*/true)
13510b57cec5SDimitry Andric                                .flag("-mnan=2008")
13520b57cec5SDimitry Andric                                .flag("-muclibc");
135306c3fb27SDimitry Andric     auto BeHardUclibc = MultilibBuilder("/mips-r2-hard-uclibc")
135406c3fb27SDimitry Andric                             .flag("-EB")
135506c3fb27SDimitry Andric                             .flag("-msoft-float", /*Disallow=*/true)
135606c3fb27SDimitry Andric                             .flag("-mnan=2008", /*Disallow=*/true)
135706c3fb27SDimitry Andric                             .flag("-muclibc");
135806c3fb27SDimitry Andric     auto ElHardUclibc = MultilibBuilder("/mipsel-r2-hard-uclibc")
135906c3fb27SDimitry Andric                             .flag("-EL")
136006c3fb27SDimitry Andric                             .flag("-msoft-float", /*Disallow=*/true)
136106c3fb27SDimitry Andric                             .flag("-mnan=2008", /*Disallow=*/true)
136206c3fb27SDimitry Andric                             .flag("-muclibc");
136306c3fb27SDimitry Andric     auto ElMicroHardNan = MultilibBuilder("/micromipsel-r2-hard-nan2008")
136406c3fb27SDimitry Andric                               .flag("-EL")
136506c3fb27SDimitry Andric                               .flag("-msoft-float", /*Disallow=*/true)
13660b57cec5SDimitry Andric                               .flag("-mnan=2008")
13670b57cec5SDimitry Andric                               .flag("-mmicromips");
136806c3fb27SDimitry Andric     auto ElMicroSoft = MultilibBuilder("/micromipsel-r2-soft")
136906c3fb27SDimitry Andric                            .flag("-EL")
13700b57cec5SDimitry Andric                            .flag("-msoft-float")
137106c3fb27SDimitry Andric                            .flag("-mnan=2008", /*Disallow=*/true)
13720b57cec5SDimitry Andric                            .flag("-mmicromips");
13730b57cec5SDimitry Andric 
137406c3fb27SDimitry Andric     auto O32 = MultilibBuilder("/lib")
137506c3fb27SDimitry Andric                    .osSuffix("")
137606c3fb27SDimitry Andric                    .flag("-mabi=n32", /*Disallow=*/true)
137706c3fb27SDimitry Andric                    .flag("-mabi=n64", /*Disallow=*/true);
137806c3fb27SDimitry Andric     auto N32 = MultilibBuilder("/lib32")
137906c3fb27SDimitry Andric                    .osSuffix("")
138006c3fb27SDimitry Andric                    .flag("-mabi=n32")
138106c3fb27SDimitry Andric                    .flag("-mabi=n64", /*Disallow=*/true);
138206c3fb27SDimitry Andric     auto N64 = MultilibBuilder("/lib64")
138306c3fb27SDimitry Andric                    .osSuffix("")
138406c3fb27SDimitry Andric                    .flag("-mabi=n32", /*Disallow=*/true)
138506c3fb27SDimitry Andric                    .flag("-mabi=n64");
13860b57cec5SDimitry Andric 
13870b57cec5SDimitry Andric     MtiMipsMultilibsV2 =
138806c3fb27SDimitry Andric         MultilibSetBuilder()
13890b57cec5SDimitry Andric             .Either({BeHard, BeSoft, ElHard, ElSoft, BeHardNan, ElHardNan,
13900b57cec5SDimitry Andric                      BeHardNanUclibc, ElHardNanUclibc, BeHardUclibc,
13910b57cec5SDimitry Andric                      ElHardUclibc, ElMicroHardNan, ElMicroSoft})
13920b57cec5SDimitry Andric             .Either(O32, N32, N64)
139306c3fb27SDimitry Andric             .makeMultilibSet()
13940b57cec5SDimitry Andric             .FilterOut(NonExistent)
13950b57cec5SDimitry Andric             .setIncludeDirsCallback([](const Multilib &M) {
13960b57cec5SDimitry Andric               return std::vector<std::string>({"/../../../../sysroot" +
13970b57cec5SDimitry Andric                                                M.includeSuffix() +
13980b57cec5SDimitry Andric                                                "/../usr/include"});
13990b57cec5SDimitry Andric             })
14000b57cec5SDimitry Andric             .setFilePathsCallback([](const Multilib &M) {
14010b57cec5SDimitry Andric               return std::vector<std::string>(
14020b57cec5SDimitry Andric                   {"/../../../../mips-mti-linux-gnu/lib" + M.gccSuffix()});
14030b57cec5SDimitry Andric             });
14040b57cec5SDimitry Andric   }
1405bdd1243dSDimitry Andric   for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
140606c3fb27SDimitry Andric     if (Candidate->select(Flags, Result.SelectedMultilibs)) {
14070b57cec5SDimitry Andric       Result.Multilibs = *Candidate;
14080b57cec5SDimitry Andric       return true;
14090b57cec5SDimitry Andric     }
14100b57cec5SDimitry Andric   }
14110b57cec5SDimitry Andric   return false;
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
14150b57cec5SDimitry Andric                                  FilterNonExistent &NonExistent,
14160b57cec5SDimitry Andric                                  DetectedMultilibs &Result) {
14170b57cec5SDimitry Andric   // CodeScape IMG toolchain v1.2 and early.
14180b57cec5SDimitry Andric   MultilibSet ImgMultilibsV1;
14190b57cec5SDimitry Andric   {
142006c3fb27SDimitry Andric     auto Mips64r6 = MultilibBuilder("/mips64r6")
142106c3fb27SDimitry Andric                         .flag("-m64")
142206c3fb27SDimitry Andric                         .flag("-m32", /*Disallow=*/true);
14230b57cec5SDimitry Andric 
142406c3fb27SDimitry Andric     auto LittleEndian =
142506c3fb27SDimitry Andric         MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
14260b57cec5SDimitry Andric 
142706c3fb27SDimitry Andric     auto MAbi64 = MultilibBuilder("/64")
142806c3fb27SDimitry Andric                       .flag("-mabi=n64")
142906c3fb27SDimitry Andric                       .flag("-mabi=n32", /*Disallow=*/true)
143006c3fb27SDimitry Andric                       .flag("-m32", /*Disallow=*/true);
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric     ImgMultilibsV1 =
143306c3fb27SDimitry Andric         MultilibSetBuilder()
14340b57cec5SDimitry Andric             .Maybe(Mips64r6)
14350b57cec5SDimitry Andric             .Maybe(MAbi64)
14360b57cec5SDimitry Andric             .Maybe(LittleEndian)
143706c3fb27SDimitry Andric             .makeMultilibSet()
14380b57cec5SDimitry Andric             .FilterOut(NonExistent)
14390b57cec5SDimitry Andric             .setIncludeDirsCallback([](const Multilib &M) {
14400b57cec5SDimitry Andric               return std::vector<std::string>(
14410b57cec5SDimitry Andric                   {"/include", "/../../../../sysroot/usr/include"});
14420b57cec5SDimitry Andric             });
14430b57cec5SDimitry Andric   }
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric   // CodeScape IMG toolchain starting from v1.3.
14460b57cec5SDimitry Andric   MultilibSet ImgMultilibsV2;
14470b57cec5SDimitry Andric   {
144806c3fb27SDimitry Andric     auto BeHard = MultilibBuilder("/mips-r6-hard")
144906c3fb27SDimitry Andric                       .flag("-EB")
145006c3fb27SDimitry Andric                       .flag("-msoft-float", /*Disallow=*/true)
145106c3fb27SDimitry Andric                       .flag("-mmicromips", /*Disallow=*/true);
145206c3fb27SDimitry Andric     auto BeSoft = MultilibBuilder("/mips-r6-soft")
145306c3fb27SDimitry Andric                       .flag("-EB")
145406c3fb27SDimitry Andric                       .flag("-msoft-float")
145506c3fb27SDimitry Andric                       .flag("-mmicromips", /*Disallow=*/true);
145606c3fb27SDimitry Andric     auto ElHard = MultilibBuilder("/mipsel-r6-hard")
145706c3fb27SDimitry Andric                       .flag("-EL")
145806c3fb27SDimitry Andric                       .flag("-msoft-float", /*Disallow=*/true)
145906c3fb27SDimitry Andric                       .flag("-mmicromips", /*Disallow=*/true);
146006c3fb27SDimitry Andric     auto ElSoft = MultilibBuilder("/mipsel-r6-soft")
146106c3fb27SDimitry Andric                       .flag("-EL")
146206c3fb27SDimitry Andric                       .flag("-msoft-float")
146306c3fb27SDimitry Andric                       .flag("-mmicromips", /*Disallow=*/true);
146406c3fb27SDimitry Andric     auto BeMicroHard = MultilibBuilder("/micromips-r6-hard")
146506c3fb27SDimitry Andric                            .flag("-EB")
146606c3fb27SDimitry Andric                            .flag("-msoft-float", /*Disallow=*/true)
146706c3fb27SDimitry Andric                            .flag("-mmicromips");
146806c3fb27SDimitry Andric     auto BeMicroSoft = MultilibBuilder("/micromips-r6-soft")
146906c3fb27SDimitry Andric                            .flag("-EB")
14700b57cec5SDimitry Andric                            .flag("-msoft-float")
14710b57cec5SDimitry Andric                            .flag("-mmicromips");
147206c3fb27SDimitry Andric     auto ElMicroHard = MultilibBuilder("/micromipsel-r6-hard")
147306c3fb27SDimitry Andric                            .flag("-EL")
147406c3fb27SDimitry Andric                            .flag("-msoft-float", /*Disallow=*/true)
14750b57cec5SDimitry Andric                            .flag("-mmicromips");
147606c3fb27SDimitry Andric     auto ElMicroSoft = MultilibBuilder("/micromipsel-r6-soft")
147706c3fb27SDimitry Andric                            .flag("-EL")
14780b57cec5SDimitry Andric                            .flag("-msoft-float")
14790b57cec5SDimitry Andric                            .flag("-mmicromips");
14800b57cec5SDimitry Andric 
148106c3fb27SDimitry Andric     auto O32 = MultilibBuilder("/lib")
148206c3fb27SDimitry Andric                    .osSuffix("")
148306c3fb27SDimitry Andric                    .flag("-mabi=n32", /*Disallow=*/true)
148406c3fb27SDimitry Andric                    .flag("-mabi=n64", /*Disallow=*/true);
148506c3fb27SDimitry Andric     auto N32 = MultilibBuilder("/lib32")
148606c3fb27SDimitry Andric                    .osSuffix("")
148706c3fb27SDimitry Andric                    .flag("-mabi=n32")
148806c3fb27SDimitry Andric                    .flag("-mabi=n64", /*Disallow=*/true);
148906c3fb27SDimitry Andric     auto N64 = MultilibBuilder("/lib64")
149006c3fb27SDimitry Andric                    .osSuffix("")
149106c3fb27SDimitry Andric                    .flag("-mabi=n32", /*Disallow=*/true)
149206c3fb27SDimitry Andric                    .flag("-mabi=n64");
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric     ImgMultilibsV2 =
149506c3fb27SDimitry Andric         MultilibSetBuilder()
14960b57cec5SDimitry Andric             .Either({BeHard, BeSoft, ElHard, ElSoft, BeMicroHard, BeMicroSoft,
14970b57cec5SDimitry Andric                      ElMicroHard, ElMicroSoft})
14980b57cec5SDimitry Andric             .Either(O32, N32, N64)
149906c3fb27SDimitry Andric             .makeMultilibSet()
15000b57cec5SDimitry Andric             .FilterOut(NonExistent)
15010b57cec5SDimitry Andric             .setIncludeDirsCallback([](const Multilib &M) {
15020b57cec5SDimitry Andric               return std::vector<std::string>({"/../../../../sysroot" +
15030b57cec5SDimitry Andric                                                M.includeSuffix() +
15040b57cec5SDimitry Andric                                                "/../usr/include"});
15050b57cec5SDimitry Andric             })
15060b57cec5SDimitry Andric             .setFilePathsCallback([](const Multilib &M) {
15070b57cec5SDimitry Andric               return std::vector<std::string>(
15080b57cec5SDimitry Andric                   {"/../../../../mips-img-linux-gnu/lib" + M.gccSuffix()});
15090b57cec5SDimitry Andric             });
15100b57cec5SDimitry Andric   }
1511bdd1243dSDimitry Andric   for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
151206c3fb27SDimitry Andric     if (Candidate->select(Flags, Result.SelectedMultilibs)) {
15130b57cec5SDimitry Andric       Result.Multilibs = *Candidate;
15140b57cec5SDimitry Andric       return true;
15150b57cec5SDimitry Andric     }
15160b57cec5SDimitry Andric   }
15170b57cec5SDimitry Andric   return false;
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric bool clang::driver::findMIPSMultilibs(const Driver &D,
15210b57cec5SDimitry Andric                                       const llvm::Triple &TargetTriple,
15220b57cec5SDimitry Andric                                       StringRef Path, const ArgList &Args,
15230b57cec5SDimitry Andric                                       DetectedMultilibs &Result) {
15240b57cec5SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   StringRef CPUName;
15270b57cec5SDimitry Andric   StringRef ABIName;
15280b57cec5SDimitry Andric   tools::mips::getMipsCPUAndABI(Args, TargetTriple, CPUName, ABIName);
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric   llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric   Multilib::flags_list Flags;
153306c3fb27SDimitry Andric   addMultilibFlag(TargetTriple.isMIPS32(), "-m32", Flags);
153406c3fb27SDimitry Andric   addMultilibFlag(TargetTriple.isMIPS64(), "-m64", Flags);
153506c3fb27SDimitry Andric   addMultilibFlag(isMips16(Args), "-mips16", Flags);
153606c3fb27SDimitry Andric   addMultilibFlag(CPUName == "mips32", "-march=mips32", Flags);
15370b57cec5SDimitry Andric   addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
15380b57cec5SDimitry Andric                       CPUName == "mips32r5" || CPUName == "p5600",
153906c3fb27SDimitry Andric                   "-march=mips32r2", Flags);
154006c3fb27SDimitry Andric   addMultilibFlag(CPUName == "mips32r6", "-march=mips32r6", Flags);
154106c3fb27SDimitry Andric   addMultilibFlag(CPUName == "mips64", "-march=mips64", Flags);
15420b57cec5SDimitry Andric   addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
15430b57cec5SDimitry Andric                       CPUName == "mips64r5" || CPUName == "octeon" ||
15440b57cec5SDimitry Andric                       CPUName == "octeon+",
154506c3fb27SDimitry Andric                   "-march=mips64r2", Flags);
154606c3fb27SDimitry Andric   addMultilibFlag(CPUName == "mips64r6", "-march=mips64r6", Flags);
154706c3fb27SDimitry Andric   addMultilibFlag(isMicroMips(Args), "-mmicromips", Flags);
154806c3fb27SDimitry Andric   addMultilibFlag(tools::mips::isUCLibc(Args), "-muclibc", Flags);
154906c3fb27SDimitry Andric   addMultilibFlag(tools::mips::isNaN2008(D, Args, TargetTriple), "-mnan=2008",
15500b57cec5SDimitry Andric                   Flags);
155106c3fb27SDimitry Andric   addMultilibFlag(ABIName == "n32", "-mabi=n32", Flags);
155206c3fb27SDimitry Andric   addMultilibFlag(ABIName == "n64", "-mabi=n64", Flags);
155306c3fb27SDimitry Andric   addMultilibFlag(isSoftFloatABI(Args), "-msoft-float", Flags);
155406c3fb27SDimitry Andric   addMultilibFlag(!isSoftFloatABI(Args), "-mhard-float", Flags);
155506c3fb27SDimitry Andric   addMultilibFlag(isMipsEL(TargetArch), "-EL", Flags);
155606c3fb27SDimitry Andric   addMultilibFlag(!isMipsEL(TargetArch), "-EB", Flags);
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric   if (TargetTriple.isAndroid())
15590b57cec5SDimitry Andric     return findMipsAndroidMultilibs(D.getVFS(), Path, Flags, NonExistent,
15600b57cec5SDimitry Andric                                     Result);
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
15630b57cec5SDimitry Andric       TargetTriple.getOS() == llvm::Triple::Linux &&
15640b57cec5SDimitry Andric       TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
15650b57cec5SDimitry Andric     return findMipsMuslMultilibs(Flags, NonExistent, Result);
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric   if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
15680b57cec5SDimitry Andric       TargetTriple.getOS() == llvm::Triple::Linux &&
15690b57cec5SDimitry Andric       TargetTriple.isGNUEnvironment())
15700b57cec5SDimitry Andric     return findMipsMtiMultilibs(Flags, NonExistent, Result);
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
15730b57cec5SDimitry Andric       TargetTriple.getOS() == llvm::Triple::Linux &&
15740b57cec5SDimitry Andric       TargetTriple.isGNUEnvironment())
15750b57cec5SDimitry Andric     return findMipsImgMultilibs(Flags, NonExistent, Result);
15760b57cec5SDimitry Andric 
15770b57cec5SDimitry Andric   if (findMipsCsMultilibs(Flags, NonExistent, Result))
15780b57cec5SDimitry Andric     return true;
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric   // Fallback to the regular toolchain-tree structure.
15810b57cec5SDimitry Andric   Multilib Default;
15820b57cec5SDimitry Andric   Result.Multilibs.push_back(Default);
15830b57cec5SDimitry Andric   Result.Multilibs.FilterOut(NonExistent);
15840b57cec5SDimitry Andric 
158506c3fb27SDimitry Andric   if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) {
15860b57cec5SDimitry Andric     Result.BiarchSibling = Multilib();
15870b57cec5SDimitry Andric     return true;
15880b57cec5SDimitry Andric   }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric   return false;
15910b57cec5SDimitry Andric }
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric static void findAndroidArmMultilibs(const Driver &D,
15940b57cec5SDimitry Andric                                     const llvm::Triple &TargetTriple,
15950b57cec5SDimitry Andric                                     StringRef Path, const ArgList &Args,
15960b57cec5SDimitry Andric                                     DetectedMultilibs &Result) {
15970b57cec5SDimitry Andric   // Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb.
15980b57cec5SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
159906c3fb27SDimitry Andric   MultilibBuilder ArmV7Multilib = MultilibBuilder("/armv7-a")
16000b57cec5SDimitry Andric                                       .flag("-march=armv7-a")
160106c3fb27SDimitry Andric                                       .flag("-mthumb", /*Disallow=*/true);
160206c3fb27SDimitry Andric   MultilibBuilder ThumbMultilib = MultilibBuilder("/thumb")
160306c3fb27SDimitry Andric                                       .flag("-march=armv7-a", /*Disallow=*/true)
16040b57cec5SDimitry Andric                                       .flag("-mthumb");
160506c3fb27SDimitry Andric   MultilibBuilder ArmV7ThumbMultilib =
160606c3fb27SDimitry Andric       MultilibBuilder("/armv7-a/thumb").flag("-march=armv7-a").flag("-mthumb");
160706c3fb27SDimitry Andric   MultilibBuilder DefaultMultilib =
160806c3fb27SDimitry Andric       MultilibBuilder("")
160906c3fb27SDimitry Andric           .flag("-march=armv7-a", /*Disallow=*/true)
161006c3fb27SDimitry Andric           .flag("-mthumb", /*Disallow=*/true);
16110b57cec5SDimitry Andric   MultilibSet AndroidArmMultilibs =
161206c3fb27SDimitry Andric       MultilibSetBuilder()
161306c3fb27SDimitry Andric           .Either(ThumbMultilib, ArmV7Multilib, ArmV7ThumbMultilib,
161406c3fb27SDimitry Andric                   DefaultMultilib)
161506c3fb27SDimitry Andric           .makeMultilibSet()
16160b57cec5SDimitry Andric           .FilterOut(NonExistent);
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric   Multilib::flags_list Flags;
16190b57cec5SDimitry Andric   llvm::StringRef Arch = Args.getLastArgValue(options::OPT_march_EQ);
16200b57cec5SDimitry Andric   bool IsArmArch = TargetTriple.getArch() == llvm::Triple::arm;
16210b57cec5SDimitry Andric   bool IsThumbArch = TargetTriple.getArch() == llvm::Triple::thumb;
16220b57cec5SDimitry Andric   bool IsV7SubArch = TargetTriple.getSubArch() == llvm::Triple::ARMSubArch_v7;
16230b57cec5SDimitry Andric   bool IsThumbMode = IsThumbArch ||
16240b57cec5SDimitry Andric       Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, false) ||
16250b57cec5SDimitry Andric       (IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::ISAKind::THUMB);
16260b57cec5SDimitry Andric   bool IsArmV7Mode = (IsArmArch || IsThumbArch) &&
16270b57cec5SDimitry Andric       (llvm::ARM::parseArchVersion(Arch) == 7 ||
16280b57cec5SDimitry Andric        (IsArmArch && Arch == "" && IsV7SubArch));
162906c3fb27SDimitry Andric   addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);
163006c3fb27SDimitry Andric   addMultilibFlag(IsThumbMode, "-mthumb", Flags);
16310b57cec5SDimitry Andric 
163206c3fb27SDimitry Andric   if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs))
16330b57cec5SDimitry Andric     Result.Multilibs = AndroidArmMultilibs;
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric static bool findMSP430Multilibs(const Driver &D,
16370b57cec5SDimitry Andric                                 const llvm::Triple &TargetTriple,
16380b57cec5SDimitry Andric                                 StringRef Path, const ArgList &Args,
16390b57cec5SDimitry Andric                                 DetectedMultilibs &Result) {
16400b57cec5SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
164106c3fb27SDimitry Andric   MultilibBuilder WithoutExceptions =
164206c3fb27SDimitry Andric       MultilibBuilder("/430").flag("-exceptions", /*Disallow=*/true);
164306c3fb27SDimitry Andric   MultilibBuilder WithExceptions =
164406c3fb27SDimitry Andric       MultilibBuilder("/430/exceptions").flag("-exceptions");
1645e8d8bef9SDimitry Andric 
16460b57cec5SDimitry Andric   // FIXME: when clang starts to support msp430x ISA additional logic
16470b57cec5SDimitry Andric   // to select between multilib must be implemented
164806c3fb27SDimitry Andric   // MultilibBuilder MSP430xMultilib = MultilibBuilder("/large");
16490b57cec5SDimitry Andric 
165006c3fb27SDimitry Andric   Result.Multilibs.push_back(WithoutExceptions.makeMultilib());
165106c3fb27SDimitry Andric   Result.Multilibs.push_back(WithExceptions.makeMultilib());
16520b57cec5SDimitry Andric   Result.Multilibs.FilterOut(NonExistent);
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric   Multilib::flags_list Flags;
1655e8d8bef9SDimitry Andric   addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,
1656e8d8bef9SDimitry Andric                                options::OPT_fno_exceptions, false),
165706c3fb27SDimitry Andric                   "-exceptions", Flags);
165806c3fb27SDimitry Andric   if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
16590b57cec5SDimitry Andric     return true;
16600b57cec5SDimitry Andric 
16610b57cec5SDimitry Andric   return false;
16620b57cec5SDimitry Andric }
16630b57cec5SDimitry Andric 
166481ad6265SDimitry Andric static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
166581ad6265SDimitry Andric                               StringRef Path, const ArgList &Args,
166681ad6265SDimitry Andric                               DetectedMultilibs &Result) {
166781ad6265SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
166881ad6265SDimitry Andric 
166981ad6265SDimitry Andric   tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);
1670bdd1243dSDimitry Andric   std::optional<llvm::StringRef> Res =
1671bdd1243dSDimitry Andric       tools::csky::getCSKYArchName(D, Args, TargetTriple);
167281ad6265SDimitry Andric 
167381ad6265SDimitry Andric   if (!Res)
167481ad6265SDimitry Andric     return;
167581ad6265SDimitry Andric   auto ARCHName = *Res;
167681ad6265SDimitry Andric 
167781ad6265SDimitry Andric   Multilib::flags_list Flags;
167806c3fb27SDimitry Andric   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "-hard-fp",
167981ad6265SDimitry Andric                   Flags);
168006c3fb27SDimitry Andric   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "-soft-fp",
168106c3fb27SDimitry Andric                   Flags);
168206c3fb27SDimitry Andric   addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "-soft", Flags);
168306c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck801", "-march=ck801", Flags);
168406c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck802", "-march=ck802", Flags);
168506c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck803", "-march=ck803", Flags);
168606c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck804", "-march=ck804", Flags);
168706c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck805", "-march=ck805", Flags);
168806c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck807", "-march=ck807", Flags);
168906c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck810", "-march=ck810", Flags);
169006c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck810v", "-march=ck810v", Flags);
169106c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck860", "-march=ck860", Flags);
169206c3fb27SDimitry Andric   addMultilibFlag(ARCHName == "ck860v", "-march=ck860v", Flags);
169381ad6265SDimitry Andric 
169481ad6265SDimitry Andric   bool isBigEndian = false;
169581ad6265SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
169681ad6265SDimitry Andric                                options::OPT_mbig_endian))
169781ad6265SDimitry Andric     isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
169806c3fb27SDimitry Andric   addMultilibFlag(isBigEndian, "-EB", Flags);
169981ad6265SDimitry Andric 
170006c3fb27SDimitry Andric   auto HardFloat = MultilibBuilder("/hard-fp").flag("-hard-fp");
170106c3fb27SDimitry Andric   auto SoftFpFloat = MultilibBuilder("/soft-fp").flag("-soft-fp");
170206c3fb27SDimitry Andric   auto SoftFloat = MultilibBuilder("").flag("-soft");
170306c3fb27SDimitry Andric   auto Arch801 = MultilibBuilder("/ck801").flag("-march=ck801");
170406c3fb27SDimitry Andric   auto Arch802 = MultilibBuilder("/ck802").flag("-march=ck802");
170506c3fb27SDimitry Andric   auto Arch803 = MultilibBuilder("/ck803").flag("-march=ck803");
170681ad6265SDimitry Andric   // CK804 use the same library as CK803
170706c3fb27SDimitry Andric   auto Arch804 = MultilibBuilder("/ck803").flag("-march=ck804");
170806c3fb27SDimitry Andric   auto Arch805 = MultilibBuilder("/ck805").flag("-march=ck805");
170906c3fb27SDimitry Andric   auto Arch807 = MultilibBuilder("/ck807").flag("-march=ck807");
171006c3fb27SDimitry Andric   auto Arch810 = MultilibBuilder("").flag("-march=ck810");
171106c3fb27SDimitry Andric   auto Arch810v = MultilibBuilder("/ck810v").flag("-march=ck810v");
171206c3fb27SDimitry Andric   auto Arch860 = MultilibBuilder("/ck860").flag("-march=ck860");
171306c3fb27SDimitry Andric   auto Arch860v = MultilibBuilder("/ck860v").flag("-march=ck860v");
171406c3fb27SDimitry Andric   auto BigEndian = MultilibBuilder("/big").flag("-EB");
171581ad6265SDimitry Andric 
171681ad6265SDimitry Andric   MultilibSet CSKYMultilibs =
171706c3fb27SDimitry Andric       MultilibSetBuilder()
171881ad6265SDimitry Andric           .Maybe(BigEndian)
171981ad6265SDimitry Andric           .Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,
172081ad6265SDimitry Andric                    Arch810, Arch810v, Arch860, Arch860v})
172181ad6265SDimitry Andric           .Either(HardFloat, SoftFpFloat, SoftFloat)
172206c3fb27SDimitry Andric           .makeMultilibSet()
172381ad6265SDimitry Andric           .FilterOut(NonExistent);
172481ad6265SDimitry Andric 
172506c3fb27SDimitry Andric   if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs))
172681ad6265SDimitry Andric     Result.Multilibs = CSKYMultilibs;
172781ad6265SDimitry Andric }
172881ad6265SDimitry Andric 
1729cb14a3feSDimitry Andric /// Extend the multi-lib re-use selection mechanism for RISC-V.
1730cb14a3feSDimitry Andric /// This function will try to re-use multi-lib if they are compatible.
1731cb14a3feSDimitry Andric /// Definition of compatible:
1732cb14a3feSDimitry Andric ///   - ABI must be the same.
1733cb14a3feSDimitry Andric ///   - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im
1734cb14a3feSDimitry Andric ///     is a subset of march=rv32imc.
1735cb14a3feSDimitry Andric ///   - march that contains atomic extension can't reuse multi-lib that
1736cb14a3feSDimitry Andric ///     doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and
1737cb14a3feSDimitry Andric ///     march=rv32ima are not compatible, because software and hardware
1738cb14a3feSDimitry Andric ///     atomic operation can't work together correctly.
1739cb14a3feSDimitry Andric static bool
1740cb14a3feSDimitry Andric selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch,
1741cb14a3feSDimitry Andric                     const Multilib::flags_list &Flags,
1742cb14a3feSDimitry Andric                     llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {
1743cb14a3feSDimitry Andric   // Try to find the perfect matching multi-lib first.
1744cb14a3feSDimitry Andric   if (RISCVMultilibSet.select(Flags, SelectedMultilibs))
1745cb14a3feSDimitry Andric     return true;
1746cb14a3feSDimitry Andric 
1747cb14a3feSDimitry Andric   Multilib::flags_list NewFlags;
1748cb14a3feSDimitry Andric   std::vector<MultilibBuilder> NewMultilibs;
1749cb14a3feSDimitry Andric 
1750cb14a3feSDimitry Andric   llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult =
1751cb14a3feSDimitry Andric       llvm::RISCVISAInfo::parseArchString(
1752cb14a3feSDimitry Andric           Arch, /*EnableExperimentalExtension=*/true,
1753cb14a3feSDimitry Andric           /*ExperimentalExtensionVersionCheck=*/false);
1754cb14a3feSDimitry Andric   // Ignore any error here, we assume it will be handled in another place.
1755647cbc5dSDimitry Andric   if (llvm::errorToBool(ParseResult.takeError()))
1756cb14a3feSDimitry Andric     return false;
1757cb14a3feSDimitry Andric 
1758cb14a3feSDimitry Andric   auto &ISAInfo = *ParseResult;
1759cb14a3feSDimitry Andric 
1760cb14a3feSDimitry Andric   addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags);
1761cb14a3feSDimitry Andric   addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags);
1762cb14a3feSDimitry Andric 
1763cb14a3feSDimitry Andric   // Collect all flags except march=*
1764cb14a3feSDimitry Andric   for (StringRef Flag : Flags) {
1765cb14a3feSDimitry Andric     if (Flag.starts_with("!march=") || Flag.starts_with("-march="))
1766cb14a3feSDimitry Andric       continue;
1767cb14a3feSDimitry Andric 
1768cb14a3feSDimitry Andric     NewFlags.push_back(Flag.str());
1769cb14a3feSDimitry Andric   }
1770cb14a3feSDimitry Andric 
1771cb14a3feSDimitry Andric   llvm::StringSet<> AllArchExts;
1772cb14a3feSDimitry Andric   // Reconstruct multi-lib list, and break march option into separated
1773cb14a3feSDimitry Andric   // extension. e.g. march=rv32im -> +i +m
1774cb14a3feSDimitry Andric   for (const auto &M : RISCVMultilibSet) {
1775cb14a3feSDimitry Andric     bool Skip = false;
1776cb14a3feSDimitry Andric 
1777cb14a3feSDimitry Andric     MultilibBuilder NewMultilib =
1778cb14a3feSDimitry Andric         MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix());
1779cb14a3feSDimitry Andric     for (StringRef Flag : M.flags()) {
1780cb14a3feSDimitry Andric       // Add back all flags except -march.
1781cb14a3feSDimitry Andric       if (!Flag.consume_front("-march=")) {
1782cb14a3feSDimitry Andric         NewMultilib.flag(Flag);
1783cb14a3feSDimitry Andric         continue;
1784cb14a3feSDimitry Andric       }
1785cb14a3feSDimitry Andric 
1786cb14a3feSDimitry Andric       // Break down -march into individual extension.
1787cb14a3feSDimitry Andric       llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult =
1788cb14a3feSDimitry Andric           llvm::RISCVISAInfo::parseArchString(
1789cb14a3feSDimitry Andric               Flag, /*EnableExperimentalExtension=*/true,
1790cb14a3feSDimitry Andric               /*ExperimentalExtensionVersionCheck=*/false);
1791cb14a3feSDimitry Andric       // Ignore any error here, we assume it will handled in another place.
1792647cbc5dSDimitry Andric       if (llvm::errorToBool(MLConfigParseResult.takeError())) {
1793cb14a3feSDimitry Andric         // We might get a parsing error if rv32e in the list, we could just skip
1794cb14a3feSDimitry Andric         // that and process the rest of multi-lib configs.
1795cb14a3feSDimitry Andric         Skip = true;
1796cb14a3feSDimitry Andric         continue;
1797cb14a3feSDimitry Andric       }
1798cb14a3feSDimitry Andric       auto &MLConfigISAInfo = *MLConfigParseResult;
1799cb14a3feSDimitry Andric 
18000fca6ea1SDimitry Andric       for (auto &MLConfigArchExt : MLConfigISAInfo->getExtensions()) {
1801cb14a3feSDimitry Andric         auto ExtName = MLConfigArchExt.first;
1802cb14a3feSDimitry Andric         NewMultilib.flag(Twine("-", ExtName).str());
1803cb14a3feSDimitry Andric 
1804cb14a3feSDimitry Andric         if (AllArchExts.insert(ExtName).second) {
1805cb14a3feSDimitry Andric           addMultilibFlag(ISAInfo->hasExtension(ExtName),
1806cb14a3feSDimitry Andric                           Twine("-", ExtName).str(), NewFlags);
1807cb14a3feSDimitry Andric         }
1808cb14a3feSDimitry Andric       }
1809cb14a3feSDimitry Andric 
1810cb14a3feSDimitry Andric       // Check the XLEN explicitly.
1811cb14a3feSDimitry Andric       if (MLConfigISAInfo->getXLen() == 32) {
1812cb14a3feSDimitry Andric         NewMultilib.flag("-m32");
1813cb14a3feSDimitry Andric         NewMultilib.flag("-m64", /*Disallow*/ true);
1814cb14a3feSDimitry Andric       } else {
1815cb14a3feSDimitry Andric         NewMultilib.flag("-m32", /*Disallow*/ true);
1816cb14a3feSDimitry Andric         NewMultilib.flag("-m64");
1817cb14a3feSDimitry Andric       }
1818cb14a3feSDimitry Andric 
1819cb14a3feSDimitry Andric       // Atomic extension must be explicitly checked, soft and hard atomic
1820cb14a3feSDimitry Andric       // operation never co-work correctly.
1821cb14a3feSDimitry Andric       if (!MLConfigISAInfo->hasExtension("a"))
1822cb14a3feSDimitry Andric         NewMultilib.flag("-a", /*Disallow*/ true);
1823cb14a3feSDimitry Andric     }
1824cb14a3feSDimitry Andric 
1825cb14a3feSDimitry Andric     if (Skip)
1826cb14a3feSDimitry Andric       continue;
1827cb14a3feSDimitry Andric 
1828cb14a3feSDimitry Andric     NewMultilibs.emplace_back(NewMultilib);
1829cb14a3feSDimitry Andric   }
1830cb14a3feSDimitry Andric 
1831cb14a3feSDimitry Andric   // Build an internal used only multi-lib list, used for checking any
1832cb14a3feSDimitry Andric   // compatible multi-lib.
1833cb14a3feSDimitry Andric   MultilibSet NewRISCVMultilibs =
1834cb14a3feSDimitry Andric       MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();
1835cb14a3feSDimitry Andric 
1836cb14a3feSDimitry Andric   if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs))
1837cb14a3feSDimitry Andric     for (const Multilib &NewSelectedM : SelectedMultilibs)
1838cb14a3feSDimitry Andric       for (const auto &M : RISCVMultilibSet)
1839cb14a3feSDimitry Andric         // Look up the corresponding multi-lib entry in original multi-lib set.
1840cb14a3feSDimitry Andric         if (M.gccSuffix() == NewSelectedM.gccSuffix())
1841cb14a3feSDimitry Andric           return true;
1842cb14a3feSDimitry Andric 
1843cb14a3feSDimitry Andric   return false;
1844cb14a3feSDimitry Andric }
1845cb14a3feSDimitry Andric 
1846480093f4SDimitry Andric static void findRISCVBareMetalMultilibs(const Driver &D,
1847480093f4SDimitry Andric                                         const llvm::Triple &TargetTriple,
1848480093f4SDimitry Andric                                         StringRef Path, const ArgList &Args,
1849480093f4SDimitry Andric                                         DetectedMultilibs &Result) {
1850480093f4SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1851480093f4SDimitry Andric   struct RiscvMultilib {
1852480093f4SDimitry Andric     StringRef march;
1853480093f4SDimitry Andric     StringRef mabi;
1854480093f4SDimitry Andric   };
1855480093f4SDimitry Andric   // currently only support the set of multilibs like riscv-gnu-toolchain does.
1856480093f4SDimitry Andric   // TODO: support MULTILIB_REUSE
18575ffd83dbSDimitry Andric   constexpr RiscvMultilib RISCVMultilibSet[] = {
1858480093f4SDimitry Andric       {"rv32i", "ilp32"},     {"rv32im", "ilp32"},     {"rv32iac", "ilp32"},
1859480093f4SDimitry Andric       {"rv32imac", "ilp32"},  {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
1860480093f4SDimitry Andric       {"rv64imafdc", "lp64d"}};
1861480093f4SDimitry Andric 
186206c3fb27SDimitry Andric   std::vector<MultilibBuilder> Ms;
1863480093f4SDimitry Andric   for (auto Element : RISCVMultilibSet) {
1864480093f4SDimitry Andric     // multilib path rule is ${march}/${mabi}
1865480093f4SDimitry Andric     Ms.emplace_back(
186606c3fb27SDimitry Andric         MultilibBuilder(
186706c3fb27SDimitry Andric             (Twine(Element.march) + "/" + Twine(Element.mabi)).str())
186806c3fb27SDimitry Andric             .flag(Twine("-march=", Element.march).str())
186906c3fb27SDimitry Andric             .flag(Twine("-mabi=", Element.mabi).str()));
1870480093f4SDimitry Andric   }
1871480093f4SDimitry Andric   MultilibSet RISCVMultilibs =
187206c3fb27SDimitry Andric       MultilibSetBuilder()
187306c3fb27SDimitry Andric           .Either(Ms)
187406c3fb27SDimitry Andric           .makeMultilibSet()
1875480093f4SDimitry Andric           .FilterOut(NonExistent)
1876480093f4SDimitry Andric           .setFilePathsCallback([](const Multilib &M) {
1877480093f4SDimitry Andric             return std::vector<std::string>(
1878480093f4SDimitry Andric                 {M.gccSuffix(),
1879480093f4SDimitry Andric                  "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),
1880480093f4SDimitry Andric                  "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
1881480093f4SDimitry Andric           });
1882480093f4SDimitry Andric 
1883480093f4SDimitry Andric   Multilib::flags_list Flags;
1884480093f4SDimitry Andric   llvm::StringSet<> Added_ABIs;
1885480093f4SDimitry Andric   StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
18860fca6ea1SDimitry Andric   std::string MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
1887480093f4SDimitry Andric   for (auto Element : RISCVMultilibSet) {
1888480093f4SDimitry Andric     addMultilibFlag(MArch == Element.march,
188906c3fb27SDimitry Andric                     Twine("-march=", Element.march).str().c_str(), Flags);
1890480093f4SDimitry Andric     if (!Added_ABIs.count(Element.mabi)) {
1891480093f4SDimitry Andric       Added_ABIs.insert(Element.mabi);
1892480093f4SDimitry Andric       addMultilibFlag(ABIName == Element.mabi,
189306c3fb27SDimitry Andric                       Twine("-mabi=", Element.mabi).str().c_str(), Flags);
1894480093f4SDimitry Andric     }
1895480093f4SDimitry Andric   }
1896480093f4SDimitry Andric 
1897cb14a3feSDimitry Andric   if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags,
1898cb14a3feSDimitry Andric                           Result.SelectedMultilibs))
1899480093f4SDimitry Andric     Result.Multilibs = RISCVMultilibs;
1900480093f4SDimitry Andric }
1901480093f4SDimitry Andric 
19020b57cec5SDimitry Andric static void findRISCVMultilibs(const Driver &D,
19030b57cec5SDimitry Andric                                const llvm::Triple &TargetTriple, StringRef Path,
19040b57cec5SDimitry Andric                                const ArgList &Args, DetectedMultilibs &Result) {
1905480093f4SDimitry Andric   if (TargetTriple.getOS() == llvm::Triple::UnknownOS)
1906480093f4SDimitry Andric     return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
190906c3fb27SDimitry Andric   MultilibBuilder Ilp32 =
191006c3fb27SDimitry Andric       MultilibBuilder("lib32/ilp32").flag("-m32").flag("-mabi=ilp32");
191106c3fb27SDimitry Andric   MultilibBuilder Ilp32f =
191206c3fb27SDimitry Andric       MultilibBuilder("lib32/ilp32f").flag("-m32").flag("-mabi=ilp32f");
191306c3fb27SDimitry Andric   MultilibBuilder Ilp32d =
191406c3fb27SDimitry Andric       MultilibBuilder("lib32/ilp32d").flag("-m32").flag("-mabi=ilp32d");
191506c3fb27SDimitry Andric   MultilibBuilder Lp64 =
191606c3fb27SDimitry Andric       MultilibBuilder("lib64/lp64").flag("-m64").flag("-mabi=lp64");
191706c3fb27SDimitry Andric   MultilibBuilder Lp64f =
191806c3fb27SDimitry Andric       MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");
191906c3fb27SDimitry Andric   MultilibBuilder Lp64d =
192006c3fb27SDimitry Andric       MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");
19210b57cec5SDimitry Andric   MultilibSet RISCVMultilibs =
192206c3fb27SDimitry Andric       MultilibSetBuilder()
19230b57cec5SDimitry Andric           .Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
192406c3fb27SDimitry Andric           .makeMultilibSet()
19250b57cec5SDimitry Andric           .FilterOut(NonExistent);
19260b57cec5SDimitry Andric 
19270b57cec5SDimitry Andric   Multilib::flags_list Flags;
19280b57cec5SDimitry Andric   bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
19290b57cec5SDimitry Andric   StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
19300b57cec5SDimitry Andric 
193106c3fb27SDimitry Andric   addMultilibFlag(!IsRV64, "-m32", Flags);
193206c3fb27SDimitry Andric   addMultilibFlag(IsRV64, "-m64", Flags);
193306c3fb27SDimitry Andric   addMultilibFlag(ABIName == "ilp32", "-mabi=ilp32", Flags);
193406c3fb27SDimitry Andric   addMultilibFlag(ABIName == "ilp32f", "-mabi=ilp32f", Flags);
193506c3fb27SDimitry Andric   addMultilibFlag(ABIName == "ilp32d", "-mabi=ilp32d", Flags);
193606c3fb27SDimitry Andric   addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);
193706c3fb27SDimitry Andric   addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
193806c3fb27SDimitry Andric   addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
19390b57cec5SDimitry Andric 
194006c3fb27SDimitry Andric   if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs))
19410b57cec5SDimitry Andric     Result.Multilibs = RISCVMultilibs;
19420b57cec5SDimitry Andric }
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric static bool findBiarchMultilibs(const Driver &D,
19450b57cec5SDimitry Andric                                 const llvm::Triple &TargetTriple,
19460b57cec5SDimitry Andric                                 StringRef Path, const ArgList &Args,
19470b57cec5SDimitry Andric                                 bool NeedsBiarchSuffix,
19480b57cec5SDimitry Andric                                 DetectedMultilibs &Result) {
194906c3fb27SDimitry Andric   MultilibBuilder DefaultBuilder;
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric   // Some versions of SUSE and Fedora on ppc64 put 32-bit libs
19520b57cec5SDimitry Andric   // in what would normally be GCCInstallPath and put the 64-bit
19530b57cec5SDimitry Andric   // libs in a subdirectory named 64. The simple logic we follow is that
19540b57cec5SDimitry Andric   // *if* there is a subdirectory of the right name with crtbegin.o in it,
19550b57cec5SDimitry Andric   // we use that. If not, and if not a biarch triple alias, we look for
19560b57cec5SDimitry Andric   // crtbegin.o without the subdirectory.
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   StringRef Suff64 = "/64";
19590b57cec5SDimitry Andric   // Solaris uses platform-specific suffixes instead of /64.
19605f757f3fSDimitry Andric   if (TargetTriple.isOSSolaris()) {
19610b57cec5SDimitry Andric     switch (TargetTriple.getArch()) {
19620b57cec5SDimitry Andric     case llvm::Triple::x86:
19630b57cec5SDimitry Andric     case llvm::Triple::x86_64:
19640b57cec5SDimitry Andric       Suff64 = "/amd64";
19650b57cec5SDimitry Andric       break;
19660b57cec5SDimitry Andric     case llvm::Triple::sparc:
19670b57cec5SDimitry Andric     case llvm::Triple::sparcv9:
19680b57cec5SDimitry Andric       Suff64 = "/sparcv9";
19690b57cec5SDimitry Andric       break;
19700b57cec5SDimitry Andric     default:
19710b57cec5SDimitry Andric       break;
19720b57cec5SDimitry Andric     }
19730b57cec5SDimitry Andric   }
19740b57cec5SDimitry Andric 
197506c3fb27SDimitry Andric   Multilib Alt64 = MultilibBuilder()
19760b57cec5SDimitry Andric                        .gccSuffix(Suff64)
19770b57cec5SDimitry Andric                        .includeSuffix(Suff64)
197806c3fb27SDimitry Andric                        .flag("-m32", /*Disallow=*/true)
197906c3fb27SDimitry Andric                        .flag("-m64")
198006c3fb27SDimitry Andric                        .flag("-mx32", /*Disallow=*/true)
198106c3fb27SDimitry Andric                        .makeMultilib();
198206c3fb27SDimitry Andric   Multilib Alt32 = MultilibBuilder()
19830b57cec5SDimitry Andric                        .gccSuffix("/32")
19840b57cec5SDimitry Andric                        .includeSuffix("/32")
198506c3fb27SDimitry Andric                        .flag("-m32")
198606c3fb27SDimitry Andric                        .flag("-m64", /*Disallow=*/true)
198706c3fb27SDimitry Andric                        .flag("-mx32", /*Disallow=*/true)
198806c3fb27SDimitry Andric                        .makeMultilib();
198906c3fb27SDimitry Andric   Multilib Altx32 = MultilibBuilder()
19900b57cec5SDimitry Andric                         .gccSuffix("/x32")
19910b57cec5SDimitry Andric                         .includeSuffix("/x32")
199206c3fb27SDimitry Andric                         .flag("-m32", /*Disallow=*/true)
199306c3fb27SDimitry Andric                         .flag("-m64", /*Disallow=*/true)
199406c3fb27SDimitry Andric                         .flag("-mx32")
199506c3fb27SDimitry Andric                         .makeMultilib();
19968a4dda33SDimitry Andric   Multilib Alt32sparc = MultilibBuilder()
19978a4dda33SDimitry Andric                             .gccSuffix("/sparcv8plus")
19988a4dda33SDimitry Andric                             .includeSuffix("/sparcv8plus")
19998a4dda33SDimitry Andric                             .flag("-m32")
20008a4dda33SDimitry Andric                             .flag("-m64", /*Disallow=*/true)
20018a4dda33SDimitry Andric                             .makeMultilib();
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric   // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.
20040b57cec5SDimitry Andric   FilterNonExistent NonExistent(
20050b57cec5SDimitry Andric       Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", D.getVFS());
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric   // Determine default multilib from: 32, 64, x32
20080b57cec5SDimitry Andric   // Also handle cases such as 64 on 32, 32 on 64, etc.
20090b57cec5SDimitry Andric   enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;
2010fe6060f1SDimitry Andric   const bool IsX32 = TargetTriple.isX32();
20110b57cec5SDimitry Andric   if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
20120b57cec5SDimitry Andric     Want = WANT64;
20138a4dda33SDimitry Andric   if (TargetTriple.isArch32Bit() && !NonExistent(Alt32sparc))
20148a4dda33SDimitry Andric     Want = WANT64;
20150b57cec5SDimitry Andric   else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
20160b57cec5SDimitry Andric     Want = WANT64;
20170b57cec5SDimitry Andric   else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64))
20180b57cec5SDimitry Andric     Want = WANT32;
20198a4dda33SDimitry Andric   else if (TargetTriple.isArch64Bit() && !NonExistent(Alt32sparc))
20208a4dda33SDimitry Andric     Want = WANT64;
20210b57cec5SDimitry Andric   else {
20220b57cec5SDimitry Andric     if (TargetTriple.isArch32Bit())
20230b57cec5SDimitry Andric       Want = NeedsBiarchSuffix ? WANT64 : WANT32;
20240b57cec5SDimitry Andric     else if (IsX32)
20250b57cec5SDimitry Andric       Want = NeedsBiarchSuffix ? WANT64 : WANTX32;
20260b57cec5SDimitry Andric     else
20270b57cec5SDimitry Andric       Want = NeedsBiarchSuffix ? WANT32 : WANT64;
20280b57cec5SDimitry Andric   }
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   if (Want == WANT32)
203106c3fb27SDimitry Andric     DefaultBuilder.flag("-m32")
203206c3fb27SDimitry Andric         .flag("-m64", /*Disallow=*/true)
203306c3fb27SDimitry Andric         .flag("-mx32", /*Disallow=*/true);
20340b57cec5SDimitry Andric   else if (Want == WANT64)
203506c3fb27SDimitry Andric     DefaultBuilder.flag("-m32", /*Disallow=*/true)
203606c3fb27SDimitry Andric         .flag("-m64")
203706c3fb27SDimitry Andric         .flag("-mx32", /*Disallow=*/true);
20380b57cec5SDimitry Andric   else if (Want == WANTX32)
203906c3fb27SDimitry Andric     DefaultBuilder.flag("-m32", /*Disallow=*/true)
204006c3fb27SDimitry Andric         .flag("-m64", /*Disallow=*/true)
204106c3fb27SDimitry Andric         .flag("-mx32");
20420b57cec5SDimitry Andric   else
20430b57cec5SDimitry Andric     return false;
20440b57cec5SDimitry Andric 
204506c3fb27SDimitry Andric   Multilib Default = DefaultBuilder.makeMultilib();
204606c3fb27SDimitry Andric 
20470b57cec5SDimitry Andric   Result.Multilibs.push_back(Default);
20480b57cec5SDimitry Andric   Result.Multilibs.push_back(Alt64);
20490b57cec5SDimitry Andric   Result.Multilibs.push_back(Alt32);
20500b57cec5SDimitry Andric   Result.Multilibs.push_back(Altx32);
20518a4dda33SDimitry Andric   Result.Multilibs.push_back(Alt32sparc);
20520b57cec5SDimitry Andric 
20530b57cec5SDimitry Andric   Result.Multilibs.FilterOut(NonExistent);
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric   Multilib::flags_list Flags;
205606c3fb27SDimitry Andric   addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "-m64", Flags);
205706c3fb27SDimitry Andric   addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);
205806c3fb27SDimitry Andric   addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);
20590b57cec5SDimitry Andric 
206006c3fb27SDimitry Andric   if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs))
20610b57cec5SDimitry Andric     return false;
20620b57cec5SDimitry Andric 
206306c3fb27SDimitry Andric   if (Result.SelectedMultilibs.back() == Alt64 ||
206406c3fb27SDimitry Andric       Result.SelectedMultilibs.back() == Alt32 ||
20658a4dda33SDimitry Andric       Result.SelectedMultilibs.back() == Altx32 ||
20668a4dda33SDimitry Andric       Result.SelectedMultilibs.back() == Alt32sparc)
20670b57cec5SDimitry Andric     Result.BiarchSibling = Default;
20680b57cec5SDimitry Andric 
20690b57cec5SDimitry Andric   return true;
20700b57cec5SDimitry Andric }
20710b57cec5SDimitry Andric 
20720b57cec5SDimitry Andric /// Generic_GCC - A tool chain using the 'gcc' command to perform
20730b57cec5SDimitry Andric /// all subcommands; this relies on gcc translating the majority of
20740b57cec5SDimitry Andric /// command line options.
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric /// Less-than for GCCVersion, implementing a Strict Weak Ordering.
20770b57cec5SDimitry Andric bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
20780b57cec5SDimitry Andric                                           int RHSPatch,
20790b57cec5SDimitry Andric                                           StringRef RHSPatchSuffix) const {
20800b57cec5SDimitry Andric   if (Major != RHSMajor)
20810b57cec5SDimitry Andric     return Major < RHSMajor;
2082bdd1243dSDimitry Andric   if (Minor != RHSMinor) {
2083bdd1243dSDimitry Andric     // Note that versions without a specified minor sort higher than those with
2084bdd1243dSDimitry Andric     // a minor.
2085bdd1243dSDimitry Andric     if (RHSMinor == -1)
2086bdd1243dSDimitry Andric       return true;
2087bdd1243dSDimitry Andric     if (Minor == -1)
2088bdd1243dSDimitry Andric       return false;
20890b57cec5SDimitry Andric     return Minor < RHSMinor;
2090bdd1243dSDimitry Andric   }
20910b57cec5SDimitry Andric   if (Patch != RHSPatch) {
20920b57cec5SDimitry Andric     // Note that versions without a specified patch sort higher than those with
20930b57cec5SDimitry Andric     // a patch.
20940b57cec5SDimitry Andric     if (RHSPatch == -1)
20950b57cec5SDimitry Andric       return true;
20960b57cec5SDimitry Andric     if (Patch == -1)
20970b57cec5SDimitry Andric       return false;
20980b57cec5SDimitry Andric 
20990b57cec5SDimitry Andric     // Otherwise just sort on the patch itself.
21000b57cec5SDimitry Andric     return Patch < RHSPatch;
21010b57cec5SDimitry Andric   }
21020b57cec5SDimitry Andric   if (PatchSuffix != RHSPatchSuffix) {
21030b57cec5SDimitry Andric     // Sort empty suffixes higher.
21040b57cec5SDimitry Andric     if (RHSPatchSuffix.empty())
21050b57cec5SDimitry Andric       return true;
21060b57cec5SDimitry Andric     if (PatchSuffix.empty())
21070b57cec5SDimitry Andric       return false;
21080b57cec5SDimitry Andric 
21090b57cec5SDimitry Andric     // Provide a lexicographic sort to make this a total ordering.
21100b57cec5SDimitry Andric     return PatchSuffix < RHSPatchSuffix;
21110b57cec5SDimitry Andric   }
21120b57cec5SDimitry Andric 
21130b57cec5SDimitry Andric   // The versions are equal.
21140b57cec5SDimitry Andric   return false;
21150b57cec5SDimitry Andric }
21160b57cec5SDimitry Andric 
21170b57cec5SDimitry Andric /// Parse a GCCVersion object out of a string of text.
21180b57cec5SDimitry Andric ///
21190b57cec5SDimitry Andric /// This is the primary means of forming GCCVersion objects.
21200b57cec5SDimitry Andric /*static*/
21210b57cec5SDimitry Andric Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
21220b57cec5SDimitry Andric   const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
21230b57cec5SDimitry Andric   std::pair<StringRef, StringRef> First = VersionText.split('.');
21240b57cec5SDimitry Andric   std::pair<StringRef, StringRef> Second = First.second.split('.');
21250b57cec5SDimitry Andric 
21265f757f3fSDimitry Andric   StringRef MajorStr = First.first;
21270b57cec5SDimitry Andric   StringRef MinorStr = Second.first;
21285f757f3fSDimitry Andric   StringRef PatchStr = Second.second;
21290b57cec5SDimitry Andric 
21305f757f3fSDimitry Andric   GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
21315f757f3fSDimitry Andric 
21325f757f3fSDimitry Andric   // Parse version number strings such as:
21335f757f3fSDimitry Andric   //   5
21340b57cec5SDimitry Andric   //   4.4
21350b57cec5SDimitry Andric   //   4.4-patched
21360b57cec5SDimitry Andric   //   4.4.0
21370b57cec5SDimitry Andric   //   4.4.x
21380b57cec5SDimitry Andric   //   4.4.2-rc4
21390b57cec5SDimitry Andric   //   4.4.x-patched
21405f757f3fSDimitry Andric   //   10-win32
21415f757f3fSDimitry Andric   // Split on '.', handle 1, 2 or 3 such segments. Each segment must contain
21425f757f3fSDimitry Andric   // purely a number, except for the last one, where a non-number suffix
21435f757f3fSDimitry Andric   // is stored in PatchSuffix. The third segment is allowed to not contain
21445f757f3fSDimitry Andric   // a number at all.
21455f757f3fSDimitry Andric 
21465f757f3fSDimitry Andric   auto TryParseLastNumber = [&](StringRef Segment, int &Number,
21475f757f3fSDimitry Andric                                 std::string &OutStr) -> bool {
21485f757f3fSDimitry Andric     // Look for a number prefix and parse that, and split out any trailing
21495f757f3fSDimitry Andric     // string into GoodVersion.PatchSuffix.
21505f757f3fSDimitry Andric 
21515f757f3fSDimitry Andric     if (size_t EndNumber = Segment.find_first_not_of("0123456789")) {
21525f757f3fSDimitry Andric       StringRef NumberStr = Segment.slice(0, EndNumber);
21535f757f3fSDimitry Andric       if (NumberStr.getAsInteger(10, Number) || Number < 0)
21545f757f3fSDimitry Andric         return false;
21555f757f3fSDimitry Andric       OutStr = NumberStr;
21565f757f3fSDimitry Andric       GoodVersion.PatchSuffix = Segment.substr(EndNumber);
21575f757f3fSDimitry Andric       return true;
21580b57cec5SDimitry Andric     }
21595f757f3fSDimitry Andric     return false;
21605f757f3fSDimitry Andric   };
21615f757f3fSDimitry Andric   auto TryParseNumber = [](StringRef Segment, int &Number) -> bool {
21625f757f3fSDimitry Andric     if (Segment.getAsInteger(10, Number) || Number < 0)
21635f757f3fSDimitry Andric       return false;
21645f757f3fSDimitry Andric     return true;
21655f757f3fSDimitry Andric   };
21665f757f3fSDimitry Andric 
21675f757f3fSDimitry Andric   if (MinorStr.empty()) {
21685f757f3fSDimitry Andric     // If no minor string, major is the last segment
21695f757f3fSDimitry Andric     if (!TryParseLastNumber(MajorStr, GoodVersion.Major, GoodVersion.MajorStr))
21705f757f3fSDimitry Andric       return BadVersion;
21715f757f3fSDimitry Andric     return GoodVersion;
21720b57cec5SDimitry Andric   }
21730b57cec5SDimitry Andric 
21745f757f3fSDimitry Andric   if (!TryParseNumber(MajorStr, GoodVersion.Major))
21755f757f3fSDimitry Andric     return BadVersion;
21765f757f3fSDimitry Andric   GoodVersion.MajorStr = MajorStr;
21775f757f3fSDimitry Andric 
21785f757f3fSDimitry Andric   if (PatchStr.empty()) {
21795f757f3fSDimitry Andric     // If no patch string, minor is the last segment
21805f757f3fSDimitry Andric     if (!TryParseLastNumber(MinorStr, GoodVersion.Minor, GoodVersion.MinorStr))
21815f757f3fSDimitry Andric       return BadVersion;
21825f757f3fSDimitry Andric     return GoodVersion;
21835f757f3fSDimitry Andric   }
21845f757f3fSDimitry Andric 
21855f757f3fSDimitry Andric   if (!TryParseNumber(MinorStr, GoodVersion.Minor))
21865f757f3fSDimitry Andric     return BadVersion;
21875f757f3fSDimitry Andric   GoodVersion.MinorStr = MinorStr;
21885f757f3fSDimitry Andric 
21895f757f3fSDimitry Andric   // For the last segment, tolerate a missing number.
21905f757f3fSDimitry Andric   std::string DummyStr;
21915f757f3fSDimitry Andric   TryParseLastNumber(PatchStr, GoodVersion.Patch, DummyStr);
21920b57cec5SDimitry Andric   return GoodVersion;
21930b57cec5SDimitry Andric }
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric static llvm::StringRef getGCCToolchainDir(const ArgList &Args,
21960b57cec5SDimitry Andric                                           llvm::StringRef SysRoot) {
21970b57cec5SDimitry Andric   const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
21980b57cec5SDimitry Andric   if (A)
21990b57cec5SDimitry Andric     return A->getValue();
22000b57cec5SDimitry Andric 
22010b57cec5SDimitry Andric   // If we have a SysRoot, ignore GCC_INSTALL_PREFIX.
22020b57cec5SDimitry Andric   // GCC_INSTALL_PREFIX specifies the gcc installation for the default
22030b57cec5SDimitry Andric   // sysroot and is likely not valid with a different sysroot.
22040b57cec5SDimitry Andric   if (!SysRoot.empty())
22050b57cec5SDimitry Andric     return "";
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric   return GCC_INSTALL_PREFIX;
22080b57cec5SDimitry Andric }
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric /// Initialize a GCCInstallationDetector from the driver.
22110b57cec5SDimitry Andric ///
22120b57cec5SDimitry Andric /// This performs all of the autodetection and sets up the various paths.
22130b57cec5SDimitry Andric /// Once constructed, a GCCInstallationDetector is essentially immutable.
22140b57cec5SDimitry Andric ///
22150b57cec5SDimitry Andric /// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
22160b57cec5SDimitry Andric /// should instead pull the target out of the driver. This is currently
22170b57cec5SDimitry Andric /// necessary because the driver doesn't store the final version of the target
22180b57cec5SDimitry Andric /// triple.
22190b57cec5SDimitry Andric void Generic_GCC::GCCInstallationDetector::init(
22205f757f3fSDimitry Andric     const llvm::Triple &TargetTriple, const ArgList &Args) {
22210b57cec5SDimitry Andric   llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
22220b57cec5SDimitry Andric                                          ? TargetTriple.get64BitArchVariant()
22230b57cec5SDimitry Andric                                          : TargetTriple.get32BitArchVariant();
22240b57cec5SDimitry Andric   // The library directories which may contain GCC installations.
22250b57cec5SDimitry Andric   SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
22260b57cec5SDimitry Andric   // The compatible GCC triples for this particular architecture.
22270b57cec5SDimitry Andric   SmallVector<StringRef, 16> CandidateTripleAliases;
22280b57cec5SDimitry Andric   SmallVector<StringRef, 16> CandidateBiarchTripleAliases;
22295f757f3fSDimitry Andric   // Add some triples that we want to check first.
22305f757f3fSDimitry Andric   CandidateTripleAliases.push_back(TargetTriple.str());
22310fca6ea1SDimitry Andric   std::string TripleNoVendor, BiarchTripleNoVendor;
22320fca6ea1SDimitry Andric   if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) {
22330fca6ea1SDimitry Andric     StringRef OSEnv = TargetTriple.getOSAndEnvironmentName();
22340fca6ea1SDimitry Andric     if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32)
22350fca6ea1SDimitry Andric       OSEnv = "linux-gnu";
22360fca6ea1SDimitry Andric     TripleNoVendor = (TargetTriple.getArchName().str() + '-' + OSEnv).str();
22375f757f3fSDimitry Andric     CandidateTripleAliases.push_back(TripleNoVendor);
22380fca6ea1SDimitry Andric     if (BiarchVariantTriple.getArch() != llvm::Triple::UnknownArch) {
22390fca6ea1SDimitry Andric       BiarchTripleNoVendor =
22400fca6ea1SDimitry Andric           (BiarchVariantTriple.getArchName().str() + '-' + OSEnv).str();
22410fca6ea1SDimitry Andric       CandidateBiarchTripleAliases.push_back(BiarchTripleNoVendor);
22420fca6ea1SDimitry Andric     }
22430fca6ea1SDimitry Andric   }
22445f757f3fSDimitry Andric 
22450b57cec5SDimitry Andric   CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
22460b57cec5SDimitry Andric                            CandidateTripleAliases, CandidateBiarchLibDirs,
22470b57cec5SDimitry Andric                            CandidateBiarchTripleAliases);
22480b57cec5SDimitry Andric 
2249bdd1243dSDimitry Andric   // If --gcc-install-dir= is specified, skip filesystem detection.
2250bdd1243dSDimitry Andric   if (const Arg *A =
2251bdd1243dSDimitry Andric           Args.getLastArg(clang::driver::options::OPT_gcc_install_dir_EQ);
2252bdd1243dSDimitry Andric       A && A->getValue()[0]) {
2253bdd1243dSDimitry Andric     StringRef InstallDir = A->getValue();
2254bdd1243dSDimitry Andric     if (!ScanGCCForMultilibs(TargetTriple, Args, InstallDir, false)) {
2255bdd1243dSDimitry Andric       D.Diag(diag::err_drv_invalid_gcc_install_dir) << InstallDir;
2256bdd1243dSDimitry Andric     } else {
2257bdd1243dSDimitry Andric       (void)InstallDir.consume_back("/");
2258bdd1243dSDimitry Andric       StringRef VersionText = llvm::sys::path::filename(InstallDir);
2259bdd1243dSDimitry Andric       StringRef TripleText =
2260bdd1243dSDimitry Andric           llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
2261bdd1243dSDimitry Andric 
2262bdd1243dSDimitry Andric       Version = GCCVersion::Parse(VersionText);
2263bdd1243dSDimitry Andric       GCCTriple.setTriple(TripleText);
2264bdd1243dSDimitry Andric       GCCInstallPath = std::string(InstallDir);
2265bdd1243dSDimitry Andric       GCCParentLibPath = GCCInstallPath + "/../../..";
2266bdd1243dSDimitry Andric       IsValid = true;
2267bdd1243dSDimitry Andric     }
2268bdd1243dSDimitry Andric     return;
2269bdd1243dSDimitry Andric   }
2270bdd1243dSDimitry Andric 
22711db9f3b2SDimitry Andric   // If --gcc-triple is specified use this instead of trying to
22721db9f3b2SDimitry Andric   // auto-detect a triple.
22731db9f3b2SDimitry Andric   if (const Arg *A =
22741db9f3b2SDimitry Andric           Args.getLastArg(clang::driver::options::OPT_gcc_triple_EQ)) {
22751db9f3b2SDimitry Andric     StringRef GCCTriple = A->getValue();
22761db9f3b2SDimitry Andric     CandidateTripleAliases.clear();
22771db9f3b2SDimitry Andric     CandidateTripleAliases.push_back(GCCTriple);
22781db9f3b2SDimitry Andric   }
22791db9f3b2SDimitry Andric 
22800b57cec5SDimitry Andric   // Compute the set of prefixes for our search.
2281fe6060f1SDimitry Andric   SmallVector<std::string, 8> Prefixes;
22820b57cec5SDimitry Andric   StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
22830b57cec5SDimitry Andric   if (GCCToolchainDir != "") {
22840b57cec5SDimitry Andric     if (GCCToolchainDir.back() == '/')
22850b57cec5SDimitry Andric       GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
22860b57cec5SDimitry Andric 
22875ffd83dbSDimitry Andric     Prefixes.push_back(std::string(GCCToolchainDir));
22880b57cec5SDimitry Andric   } else {
22890b57cec5SDimitry Andric     // If we have a SysRoot, try that first.
22900b57cec5SDimitry Andric     if (!D.SysRoot.empty()) {
22910b57cec5SDimitry Andric       Prefixes.push_back(D.SysRoot);
22920b57cec5SDimitry Andric       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
22930b57cec5SDimitry Andric     }
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric     // Then look for gcc installed alongside clang.
22960fca6ea1SDimitry Andric     Prefixes.push_back(D.Dir + "/..");
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric     // Next, look for prefix(es) that correspond to distribution-supplied gcc
22990b57cec5SDimitry Andric     // installations.
23000b57cec5SDimitry Andric     if (D.SysRoot.empty()) {
23010b57cec5SDimitry Andric       // Typically /usr.
23020b57cec5SDimitry Andric       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
23030b57cec5SDimitry Andric     }
23040b57cec5SDimitry Andric 
2305fe6060f1SDimitry Andric     // Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.
2306fe6060f1SDimitry Andric     // This avoids accidentally enforcing the system GCC version when using a
2307fe6060f1SDimitry Andric     // custom toolchain.
23080b57cec5SDimitry Andric     SmallVector<StringRef, 16> GentooTestTriples;
23090b57cec5SDimitry Andric     // Try to match an exact triple as target triple first.
23100b57cec5SDimitry Andric     // e.g. crossdev -S x86_64-gentoo-linux-gnu will install gcc libs for
23110b57cec5SDimitry Andric     // x86_64-gentoo-linux-gnu. But "clang -target x86_64-gentoo-linux-gnu"
23120b57cec5SDimitry Andric     // may pick the libraries for x86_64-pc-linux-gnu even when exact matching
23130b57cec5SDimitry Andric     // triple x86_64-gentoo-linux-gnu is present.
23140b57cec5SDimitry Andric     GentooTestTriples.push_back(TargetTriple.str());
23150b57cec5SDimitry Andric     GentooTestTriples.append(CandidateTripleAliases.begin(),
23160b57cec5SDimitry Andric                              CandidateTripleAliases.end());
23170b57cec5SDimitry Andric     if (ScanGentooConfigs(TargetTriple, Args, GentooTestTriples,
23180b57cec5SDimitry Andric                           CandidateBiarchTripleAliases))
23190b57cec5SDimitry Andric       return;
23200b57cec5SDimitry Andric   }
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric   // Loop over the various components which exist and select the best GCC
23230b57cec5SDimitry Andric   // installation available. GCC installs are ranked by version number.
2324fe6060f1SDimitry Andric   const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
2325fe6060f1SDimitry Andric   Version = VersionZero;
23260b57cec5SDimitry Andric   for (const std::string &Prefix : Prefixes) {
2327e8d8bef9SDimitry Andric     auto &VFS = D.getVFS();
2328e8d8bef9SDimitry Andric     if (!VFS.exists(Prefix))
23290b57cec5SDimitry Andric       continue;
23300b57cec5SDimitry Andric     for (StringRef Suffix : CandidateLibDirs) {
233181ad6265SDimitry Andric       const std::string LibDir = concat(Prefix, Suffix);
2332e8d8bef9SDimitry Andric       if (!VFS.exists(LibDir))
23330b57cec5SDimitry Andric         continue;
2334e8d8bef9SDimitry Andric       // Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.
2335e8d8bef9SDimitry Andric       bool GCCDirExists = VFS.exists(LibDir + "/gcc");
2336e8d8bef9SDimitry Andric       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
23370b57cec5SDimitry Andric       for (StringRef Candidate : CandidateTripleAliases)
2338e8d8bef9SDimitry Andric         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,
2339e8d8bef9SDimitry Andric                                GCCDirExists, GCCCrossDirExists);
23400b57cec5SDimitry Andric     }
23410b57cec5SDimitry Andric     for (StringRef Suffix : CandidateBiarchLibDirs) {
23420b57cec5SDimitry Andric       const std::string LibDir = Prefix + Suffix.str();
2343e8d8bef9SDimitry Andric       if (!VFS.exists(LibDir))
23440b57cec5SDimitry Andric         continue;
2345e8d8bef9SDimitry Andric       bool GCCDirExists = VFS.exists(LibDir + "/gcc");
2346e8d8bef9SDimitry Andric       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
23470b57cec5SDimitry Andric       for (StringRef Candidate : CandidateBiarchTripleAliases)
2348e8d8bef9SDimitry Andric         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,
2349e8d8bef9SDimitry Andric                                GCCDirExists, GCCCrossDirExists);
23500b57cec5SDimitry Andric     }
2351fe6060f1SDimitry Andric 
2352fe6060f1SDimitry Andric     // Skip other prefixes once a GCC installation is found.
2353fe6060f1SDimitry Andric     if (Version > VersionZero)
2354fe6060f1SDimitry Andric       break;
23550b57cec5SDimitry Andric   }
23560b57cec5SDimitry Andric }
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
23590b57cec5SDimitry Andric   for (const auto &InstallPath : CandidateGCCInstallPaths)
23600b57cec5SDimitry Andric     OS << "Found candidate GCC installation: " << InstallPath << "\n";
23610b57cec5SDimitry Andric 
23620b57cec5SDimitry Andric   if (!GCCInstallPath.empty())
23630b57cec5SDimitry Andric     OS << "Selected GCC installation: " << GCCInstallPath << "\n";
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   for (const auto &Multilib : Multilibs)
23660b57cec5SDimitry Andric     OS << "Candidate multilib: " << Multilib << "\n";
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric   if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
23690b57cec5SDimitry Andric     OS << "Selected multilib: " << SelectedMultilib << "\n";
23700b57cec5SDimitry Andric }
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
237381ad6265SDimitry Andric   if (BiarchSibling) {
2374bdd1243dSDimitry Andric     M = *BiarchSibling;
23750b57cec5SDimitry Andric     return true;
23760b57cec5SDimitry Andric   }
23770b57cec5SDimitry Andric   return false;
23780b57cec5SDimitry Andric }
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
23810b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes,
23820b57cec5SDimitry Andric     StringRef SysRoot) {
23835f757f3fSDimitry Andric 
23845f757f3fSDimitry Andric   if (TargetTriple.isOSHaiku()) {
23855f757f3fSDimitry Andric     Prefixes.push_back(concat(SysRoot, "/boot/system/develop/tools"));
23865f757f3fSDimitry Andric     return;
23875f757f3fSDimitry Andric   }
23885f757f3fSDimitry Andric 
23895f757f3fSDimitry Andric   if (TargetTriple.isOSSolaris()) {
23900b57cec5SDimitry Andric     // Solaris is a special case.
23910b57cec5SDimitry Andric     // The GCC installation is under
23920b57cec5SDimitry Andric     //   /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/
23930b57cec5SDimitry Andric     // so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
23940b57cec5SDimitry Andric     // /usr/gcc/<version> as a prefix.
23950b57cec5SDimitry Andric 
23968a4dda33SDimitry Andric     SmallVector<std::pair<GCCVersion, std::string>, 8> SolarisPrefixes;
239781ad6265SDimitry Andric     std::string PrefixDir = concat(SysRoot, "/usr/gcc");
23980b57cec5SDimitry Andric     std::error_code EC;
23990b57cec5SDimitry Andric     for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
24000b57cec5SDimitry Andric                                        LE;
24010b57cec5SDimitry Andric          !EC && LI != LE; LI = LI.increment(EC)) {
24020b57cec5SDimitry Andric       StringRef VersionText = llvm::sys::path::filename(LI->path());
24030b57cec5SDimitry Andric       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
24040b57cec5SDimitry Andric 
24050b57cec5SDimitry Andric       // Filter out obviously bad entries.
24060b57cec5SDimitry Andric       if (CandidateVersion.Major == -1 || CandidateVersion.isOlderThan(4, 1, 1))
24070b57cec5SDimitry Andric         continue;
24080b57cec5SDimitry Andric 
24090b57cec5SDimitry Andric       std::string CandidatePrefix = PrefixDir + "/" + VersionText.str();
24100b57cec5SDimitry Andric       std::string CandidateLibPath = CandidatePrefix + "/lib/gcc";
24110b57cec5SDimitry Andric       if (!D.getVFS().exists(CandidateLibPath))
24120b57cec5SDimitry Andric         continue;
24130b57cec5SDimitry Andric 
24148a4dda33SDimitry Andric       SolarisPrefixes.emplace_back(
24158a4dda33SDimitry Andric           std::make_pair(CandidateVersion, CandidatePrefix));
24160b57cec5SDimitry Andric     }
24178a4dda33SDimitry Andric     // Sort in reverse order so GCCInstallationDetector::init picks the latest.
24188a4dda33SDimitry Andric     std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend());
24198a4dda33SDimitry Andric     for (auto p : SolarisPrefixes)
24208a4dda33SDimitry Andric       Prefixes.emplace_back(p.second);
24210b57cec5SDimitry Andric     return;
24220b57cec5SDimitry Andric   }
24230b57cec5SDimitry Andric 
242481ad6265SDimitry Andric   // For Linux, if --sysroot is not specified, look for RHEL/CentOS devtoolsets
242581ad6265SDimitry Andric   // and gcc-toolsets.
242681ad6265SDimitry Andric   if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
242781ad6265SDimitry Andric       D.getVFS().exists("/opt/rh")) {
2428f3fd488fSDimitry Andric     // TODO: We may want to remove this, since the functionality
2429f3fd488fSDimitry Andric     //   can be achieved using config files.
2430f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr");
2431f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");
2432f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
2433f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-12/root/usr");
2434f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-11/root/usr");
2435f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");
2436f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
2437f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
2438f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
2439f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
2440f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
2441f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
2442f3fd488fSDimitry Andric     Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
244381ad6265SDimitry Andric   }
244481ad6265SDimitry Andric 
244581ad6265SDimitry Andric   // Fall back to /usr which is used by most non-Solaris systems.
244681ad6265SDimitry Andric   Prefixes.push_back(concat(SysRoot, "/usr"));
24470b57cec5SDimitry Andric }
24480b57cec5SDimitry Andric 
24490b57cec5SDimitry Andric /*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
24500b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
24510b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &LibDirs,
24520b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &TripleAliases,
24530b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &BiarchLibDirs,
24540b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &BiarchTripleAliases) {
24550b57cec5SDimitry Andric   // Declare a bunch of static data sets that we'll select between below. These
24560b57cec5SDimitry Andric   // are specifically designed to always refer to string literals to avoid any
24570b57cec5SDimitry Andric   // lifetime or initialization issues.
2458349cc55cSDimitry Andric   //
2459349cc55cSDimitry Andric   // The *Triples variables hard code some triples so that, for example,
2460349cc55cSDimitry Andric   // --target=aarch64 (incomplete triple) can detect lib/aarch64-linux-gnu.
2461349cc55cSDimitry Andric   // They are not needed when the user has correct LLVM_DEFAULT_TARGET_TRIPLE
2462349cc55cSDimitry Andric   // and always uses the full --target (e.g. --target=aarch64-linux-gnu).  The
2463349cc55cSDimitry Andric   // lists should shrink over time. Please don't add more elements to *Triples.
24640b57cec5SDimitry Andric   static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
24650b57cec5SDimitry Andric   static const char *const AArch64Triples[] = {
246662987288SDimitry Andric       "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
246762987288SDimitry Andric       "aarch64-suse-linux"};
24680b57cec5SDimitry Andric   static const char *const AArch64beLibDirs[] = {"/lib"};
24690fca6ea1SDimitry Andric   static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu"};
24700b57cec5SDimitry Andric 
24710b57cec5SDimitry Andric   static const char *const ARMLibDirs[] = {"/lib"};
2472349cc55cSDimitry Andric   static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
24730b57cec5SDimitry Andric   static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
24740b57cec5SDimitry Andric                                              "armv7hl-redhat-linux-gnueabi",
24750b57cec5SDimitry Andric                                              "armv6hl-suse-linux-gnueabi",
24760b57cec5SDimitry Andric                                              "armv7hl-suse-linux-gnueabi"};
24770b57cec5SDimitry Andric   static const char *const ARMebLibDirs[] = {"/lib"};
2478349cc55cSDimitry Andric   static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
24790b57cec5SDimitry Andric   static const char *const ARMebHFTriples[] = {
24800b57cec5SDimitry Andric       "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric   static const char *const AVRLibDirs[] = {"/lib"};
24830b57cec5SDimitry Andric   static const char *const AVRTriples[] = {"avr"};
24840b57cec5SDimitry Andric 
248581ad6265SDimitry Andric   static const char *const CSKYLibDirs[] = {"/lib"};
248681ad6265SDimitry Andric   static const char *const CSKYTriples[] = {
248781ad6265SDimitry Andric       "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};
248881ad6265SDimitry Andric 
24890b57cec5SDimitry Andric   static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
24900b57cec5SDimitry Andric   static const char *const X86_64Triples[] = {
24910b57cec5SDimitry Andric       "x86_64-linux-gnu",       "x86_64-unknown-linux-gnu",
24920b57cec5SDimitry Andric       "x86_64-pc-linux-gnu",    "x86_64-redhat-linux6E",
24930b57cec5SDimitry Andric       "x86_64-redhat-linux",    "x86_64-suse-linux",
24940fca6ea1SDimitry Andric       "x86_64-manbo-linux-gnu", "x86_64-slackware-linux",
24950fca6ea1SDimitry Andric       "x86_64-unknown-linux",   "x86_64-amazon-linux"};
2496fe6060f1SDimitry Andric   static const char *const X32Triples[] = {"x86_64-linux-gnux32",
2497fe6060f1SDimitry Andric                                            "x86_64-pc-linux-gnux32"};
2498fe6060f1SDimitry Andric   static const char *const X32LibDirs[] = {"/libx32", "/lib"};
24990b57cec5SDimitry Andric   static const char *const X86LibDirs[] = {"/lib32", "/lib"};
25000b57cec5SDimitry Andric   static const char *const X86Triples[] = {
2501349cc55cSDimitry Andric       "i586-linux-gnu",      "i686-linux-gnu",        "i686-pc-linux-gnu",
2502349cc55cSDimitry Andric       "i386-redhat-linux6E", "i686-redhat-linux",     "i386-redhat-linux",
25037a6dacacSDimitry Andric       "i586-suse-linux",     "i686-montavista-linux",
2504fe6060f1SDimitry Andric   };
2505fe6060f1SDimitry Andric 
2506bdd1243dSDimitry Andric   static const char *const LoongArch64LibDirs[] = {"/lib64", "/lib"};
2507bdd1243dSDimitry Andric   static const char *const LoongArch64Triples[] = {
2508bdd1243dSDimitry Andric       "loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"};
2509bdd1243dSDimitry Andric 
2510fe6060f1SDimitry Andric   static const char *const M68kLibDirs[] = {"/lib"};
25110fca6ea1SDimitry Andric   static const char *const M68kTriples[] = {"m68k-unknown-linux-gnu",
25120fca6ea1SDimitry Andric                                             "m68k-suse-linux"};
25130b57cec5SDimitry Andric 
2514349cc55cSDimitry Andric   static const char *const MIPSLibDirs[] = {"/libo32", "/lib"};
25150b57cec5SDimitry Andric   static const char *const MIPSTriples[] = {
25160b57cec5SDimitry Andric       "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
25170b57cec5SDimitry Andric       "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
2518349cc55cSDimitry Andric   static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"};
25190fca6ea1SDimitry Andric   static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
25200fca6ea1SDimitry Andric                                               "mips-img-linux-gnu"};
25210b57cec5SDimitry Andric 
25220b57cec5SDimitry Andric   static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
25230b57cec5SDimitry Andric   static const char *const MIPS64Triples[] = {
25240fca6ea1SDimitry Andric       "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64-linux-gnuabi64",
25250b57cec5SDimitry Andric       "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};
25260b57cec5SDimitry Andric   static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
25270b57cec5SDimitry Andric   static const char *const MIPS64ELTriples[] = {
25280fca6ea1SDimitry Andric       "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64el-linux-gnuabi64",
2529349cc55cSDimitry Andric       "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"};
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric   static const char *const MIPSN32LibDirs[] = {"/lib32"};
25320b57cec5SDimitry Andric   static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",
25330b57cec5SDimitry Andric                                                "mipsisa64r6-linux-gnuabin32"};
25340b57cec5SDimitry Andric   static const char *const MIPSN32ELLibDirs[] = {"/lib32"};
25350b57cec5SDimitry Andric   static const char *const MIPSN32ELTriples[] = {
25360b57cec5SDimitry Andric       "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"};
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   static const char *const MSP430LibDirs[] = {"/lib"};
25390b57cec5SDimitry Andric   static const char *const MSP430Triples[] = {"msp430-elf"};
25400b57cec5SDimitry Andric 
25410b57cec5SDimitry Andric   static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
25420b57cec5SDimitry Andric   static const char *const PPCTriples[] = {
25430fca6ea1SDimitry Andric       "powerpc-unknown-linux-gnu",
2544480093f4SDimitry Andric       // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a
2545480093f4SDimitry Andric       // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".
2546480093f4SDimitry Andric       "powerpc64-suse-linux", "powerpc-montavista-linuxspe"};
2547e8d8bef9SDimitry Andric   static const char *const PPCLELibDirs[] = {"/lib32", "/lib"};
25480fca6ea1SDimitry Andric   static const char *const PPCLETriples[] = {"powerpcle-unknown-linux-gnu",
2549e8d8bef9SDimitry Andric                                              "powerpcle-linux-musl"};
2550e8d8bef9SDimitry Andric 
25510b57cec5SDimitry Andric   static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};
25520fca6ea1SDimitry Andric   static const char *const PPC64Triples[] = {"powerpc64-unknown-linux-gnu",
25530fca6ea1SDimitry Andric                                              "powerpc64-suse-linux",
25540fca6ea1SDimitry Andric                                              "ppc64-redhat-linux"};
25550b57cec5SDimitry Andric   static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"};
25560b57cec5SDimitry Andric   static const char *const PPC64LETriples[] = {
25570fca6ea1SDimitry Andric       "powerpc64le-unknown-linux-gnu", "powerpc64le-none-linux-gnu",
25580fca6ea1SDimitry Andric       "powerpc64le-suse-linux", "ppc64le-redhat-linux"};
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric   static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"};
25610b57cec5SDimitry Andric   static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",
25620b57cec5SDimitry Andric                                                "riscv32-unknown-elf"};
25630b57cec5SDimitry Andric   static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
25640b57cec5SDimitry Andric   static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
2565349cc55cSDimitry Andric                                                "riscv64-unknown-elf"};
25660b57cec5SDimitry Andric 
25670b57cec5SDimitry Andric   static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
25680b57cec5SDimitry Andric   static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
25690b57cec5SDimitry Andric                                                "sparcv8-linux-gnu"};
25700b57cec5SDimitry Andric   static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
25710b57cec5SDimitry Andric   static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
25720b57cec5SDimitry Andric                                                "sparcv9-linux-gnu"};
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric   static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
25750b57cec5SDimitry Andric   static const char *const SystemZTriples[] = {
25760fca6ea1SDimitry Andric       "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux",
25770fca6ea1SDimitry Andric       "s390x-redhat-linux"};
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric   using std::begin;
25800b57cec5SDimitry Andric   using std::end;
25810b57cec5SDimitry Andric 
25825f757f3fSDimitry Andric   if (TargetTriple.isOSSolaris()) {
25830b57cec5SDimitry Andric     static const char *const SolarisLibDirs[] = {"/lib"};
25840b57cec5SDimitry Andric     static const char *const SolarisSparcV8Triples[] = {
25855f757f3fSDimitry Andric         "sparc-sun-solaris2.11"};
25860b57cec5SDimitry Andric     static const char *const SolarisSparcV9Triples[] = {
25875f757f3fSDimitry Andric         "sparcv9-sun-solaris2.11"};
25885f757f3fSDimitry Andric     static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11"};
25895f757f3fSDimitry Andric     static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11"};
25900b57cec5SDimitry Andric     LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
25910b57cec5SDimitry Andric     BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
25920b57cec5SDimitry Andric     switch (TargetTriple.getArch()) {
25930b57cec5SDimitry Andric     case llvm::Triple::x86:
25940b57cec5SDimitry Andric       TripleAliases.append(begin(SolarisX86Triples), end(SolarisX86Triples));
25950b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(SolarisX86_64Triples),
25960b57cec5SDimitry Andric                                  end(SolarisX86_64Triples));
25970b57cec5SDimitry Andric       break;
25980b57cec5SDimitry Andric     case llvm::Triple::x86_64:
25990b57cec5SDimitry Andric       TripleAliases.append(begin(SolarisX86_64Triples),
26000b57cec5SDimitry Andric                            end(SolarisX86_64Triples));
26010b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(SolarisX86Triples),
26020b57cec5SDimitry Andric                                  end(SolarisX86Triples));
26030b57cec5SDimitry Andric       break;
26040b57cec5SDimitry Andric     case llvm::Triple::sparc:
26050b57cec5SDimitry Andric       TripleAliases.append(begin(SolarisSparcV8Triples),
26060b57cec5SDimitry Andric                            end(SolarisSparcV8Triples));
26070b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(SolarisSparcV9Triples),
26080b57cec5SDimitry Andric                                  end(SolarisSparcV9Triples));
26090b57cec5SDimitry Andric       break;
26100b57cec5SDimitry Andric     case llvm::Triple::sparcv9:
26110b57cec5SDimitry Andric       TripleAliases.append(begin(SolarisSparcV9Triples),
26120b57cec5SDimitry Andric                            end(SolarisSparcV9Triples));
26130b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(SolarisSparcV8Triples),
26140b57cec5SDimitry Andric                                  end(SolarisSparcV8Triples));
26150b57cec5SDimitry Andric       break;
26160b57cec5SDimitry Andric     default:
26170b57cec5SDimitry Andric       break;
26180b57cec5SDimitry Andric     }
26190b57cec5SDimitry Andric     return;
26200b57cec5SDimitry Andric   }
26210b57cec5SDimitry Andric 
26220b57cec5SDimitry Andric   // Android targets should not use GNU/Linux tools or libraries.
26230b57cec5SDimitry Andric   if (TargetTriple.isAndroid()) {
26240b57cec5SDimitry Andric     static const char *const AArch64AndroidTriples[] = {
26250b57cec5SDimitry Andric         "aarch64-linux-android"};
26260b57cec5SDimitry Andric     static const char *const ARMAndroidTriples[] = {"arm-linux-androideabi"};
26270b57cec5SDimitry Andric     static const char *const X86AndroidTriples[] = {"i686-linux-android"};
26280b57cec5SDimitry Andric     static const char *const X86_64AndroidTriples[] = {"x86_64-linux-android"};
26290b57cec5SDimitry Andric 
26300b57cec5SDimitry Andric     switch (TargetTriple.getArch()) {
26310b57cec5SDimitry Andric     case llvm::Triple::aarch64:
26320b57cec5SDimitry Andric       LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
26330b57cec5SDimitry Andric       TripleAliases.append(begin(AArch64AndroidTriples),
26340b57cec5SDimitry Andric                            end(AArch64AndroidTriples));
26350b57cec5SDimitry Andric       break;
26360b57cec5SDimitry Andric     case llvm::Triple::arm:
26370b57cec5SDimitry Andric     case llvm::Triple::thumb:
26380b57cec5SDimitry Andric       LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
26390b57cec5SDimitry Andric       TripleAliases.append(begin(ARMAndroidTriples), end(ARMAndroidTriples));
26400b57cec5SDimitry Andric       break;
26410b57cec5SDimitry Andric     case llvm::Triple::x86_64:
26420b57cec5SDimitry Andric       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
26430b57cec5SDimitry Andric       TripleAliases.append(begin(X86_64AndroidTriples),
26440b57cec5SDimitry Andric                            end(X86_64AndroidTriples));
26450b57cec5SDimitry Andric       BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
26460b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(X86AndroidTriples),
26470b57cec5SDimitry Andric                                  end(X86AndroidTriples));
26480b57cec5SDimitry Andric       break;
26490b57cec5SDimitry Andric     case llvm::Triple::x86:
26500b57cec5SDimitry Andric       LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
26510b57cec5SDimitry Andric       TripleAliases.append(begin(X86AndroidTriples), end(X86AndroidTriples));
26520b57cec5SDimitry Andric       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
26530b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(X86_64AndroidTriples),
26540b57cec5SDimitry Andric                                  end(X86_64AndroidTriples));
26550b57cec5SDimitry Andric       break;
26560b57cec5SDimitry Andric     default:
26570b57cec5SDimitry Andric       break;
26580b57cec5SDimitry Andric     }
26590b57cec5SDimitry Andric 
26600b57cec5SDimitry Andric     return;
26610b57cec5SDimitry Andric   }
26620b57cec5SDimitry Andric 
26637a6dacacSDimitry Andric   if (TargetTriple.isOSHurd()) {
26647a6dacacSDimitry Andric     switch (TargetTriple.getArch()) {
26657a6dacacSDimitry Andric     case llvm::Triple::x86_64:
26667a6dacacSDimitry Andric       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
26677a6dacacSDimitry Andric       TripleAliases.push_back("x86_64-gnu");
26687a6dacacSDimitry Andric       break;
26697a6dacacSDimitry Andric     case llvm::Triple::x86:
26707a6dacacSDimitry Andric       LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
26717a6dacacSDimitry Andric       TripleAliases.push_back("i686-gnu");
26727a6dacacSDimitry Andric       break;
26737a6dacacSDimitry Andric     default:
26747a6dacacSDimitry Andric       break;
26757a6dacacSDimitry Andric     }
26767a6dacacSDimitry Andric 
26777a6dacacSDimitry Andric     return;
26787a6dacacSDimitry Andric   }
26797a6dacacSDimitry Andric 
26800b57cec5SDimitry Andric   switch (TargetTriple.getArch()) {
26810b57cec5SDimitry Andric   case llvm::Triple::aarch64:
26820b57cec5SDimitry Andric     LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
26830b57cec5SDimitry Andric     TripleAliases.append(begin(AArch64Triples), end(AArch64Triples));
26840b57cec5SDimitry Andric     BiarchLibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
26850b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(AArch64Triples), end(AArch64Triples));
26860b57cec5SDimitry Andric     break;
26870b57cec5SDimitry Andric   case llvm::Triple::aarch64_be:
26880b57cec5SDimitry Andric     LibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));
26890b57cec5SDimitry Andric     TripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));
26900b57cec5SDimitry Andric     BiarchLibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));
26910b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));
26920b57cec5SDimitry Andric     break;
26930b57cec5SDimitry Andric   case llvm::Triple::arm:
26940b57cec5SDimitry Andric   case llvm::Triple::thumb:
26950b57cec5SDimitry Andric     LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
2696297eecfbSDimitry Andric     if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
2697*d686ce93SDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
2698297eecfbSDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
2699297eecfbSDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
27000b57cec5SDimitry Andric       TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));
27010b57cec5SDimitry Andric     } else {
27020b57cec5SDimitry Andric       TripleAliases.append(begin(ARMTriples), end(ARMTriples));
27030b57cec5SDimitry Andric     }
27040b57cec5SDimitry Andric     break;
27050b57cec5SDimitry Andric   case llvm::Triple::armeb:
27060b57cec5SDimitry Andric   case llvm::Triple::thumbeb:
27070b57cec5SDimitry Andric     LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));
2708297eecfbSDimitry Andric     if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
2709*d686ce93SDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
2710297eecfbSDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
2711297eecfbSDimitry Andric         TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
27120b57cec5SDimitry Andric       TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));
27130b57cec5SDimitry Andric     } else {
27140b57cec5SDimitry Andric       TripleAliases.append(begin(ARMebTriples), end(ARMebTriples));
27150b57cec5SDimitry Andric     }
27160b57cec5SDimitry Andric     break;
27170b57cec5SDimitry Andric   case llvm::Triple::avr:
27180b57cec5SDimitry Andric     LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));
27190b57cec5SDimitry Andric     TripleAliases.append(begin(AVRTriples), end(AVRTriples));
27200b57cec5SDimitry Andric     break;
272181ad6265SDimitry Andric   case llvm::Triple::csky:
272281ad6265SDimitry Andric     LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));
272381ad6265SDimitry Andric     TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));
272481ad6265SDimitry Andric     break;
27250b57cec5SDimitry Andric   case llvm::Triple::x86_64:
2726fe6060f1SDimitry Andric     if (TargetTriple.isX32()) {
2727fe6060f1SDimitry Andric       LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2728fe6060f1SDimitry Andric       TripleAliases.append(begin(X32Triples), end(X32Triples));
2729fe6060f1SDimitry Andric       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
27300b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
27310b57cec5SDimitry Andric     } else {
2732fe6060f1SDimitry Andric       LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
2733fe6060f1SDimitry Andric       TripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
2734fe6060f1SDimitry Andric       BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2735fe6060f1SDimitry Andric       BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
2736fe6060f1SDimitry Andric     }
27370b57cec5SDimitry Andric     BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
27380b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(X86Triples), end(X86Triples));
27390b57cec5SDimitry Andric     break;
27400b57cec5SDimitry Andric   case llvm::Triple::x86:
27410b57cec5SDimitry Andric     LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
27420b57cec5SDimitry Andric     // MCU toolchain is 32 bit only and its triple alias is TargetTriple
27430b57cec5SDimitry Andric     // itself, which will be appended below.
27440b57cec5SDimitry Andric     if (!TargetTriple.isOSIAMCU()) {
27450b57cec5SDimitry Andric       TripleAliases.append(begin(X86Triples), end(X86Triples));
27460b57cec5SDimitry Andric       BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
27470b57cec5SDimitry Andric       BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
2748fe6060f1SDimitry Andric       BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
2749fe6060f1SDimitry Andric       BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
27500b57cec5SDimitry Andric     }
27510b57cec5SDimitry Andric     break;
2752bdd1243dSDimitry Andric   // TODO: Handle loongarch32.
2753bdd1243dSDimitry Andric   case llvm::Triple::loongarch64:
2754bdd1243dSDimitry Andric     LibDirs.append(begin(LoongArch64LibDirs), end(LoongArch64LibDirs));
2755bdd1243dSDimitry Andric     TripleAliases.append(begin(LoongArch64Triples), end(LoongArch64Triples));
2756bdd1243dSDimitry Andric     break;
2757fe6060f1SDimitry Andric   case llvm::Triple::m68k:
2758fe6060f1SDimitry Andric     LibDirs.append(begin(M68kLibDirs), end(M68kLibDirs));
2759fe6060f1SDimitry Andric     TripleAliases.append(begin(M68kTriples), end(M68kTriples));
2760fe6060f1SDimitry Andric     break;
27610b57cec5SDimitry Andric   case llvm::Triple::mips:
27620b57cec5SDimitry Andric     LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
27630b57cec5SDimitry Andric     TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
27640b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
27650b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
27660b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
27670b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
27680b57cec5SDimitry Andric     break;
27690b57cec5SDimitry Andric   case llvm::Triple::mipsel:
27700b57cec5SDimitry Andric     LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
27710b57cec5SDimitry Andric     TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
27720b57cec5SDimitry Andric     TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
27730b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
27740b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
27750b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
27760b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
27770b57cec5SDimitry Andric     break;
27780b57cec5SDimitry Andric   case llvm::Triple::mips64:
27790b57cec5SDimitry Andric     LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
27800b57cec5SDimitry Andric     TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
27810b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
27820b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
27830b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
27840b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
27850b57cec5SDimitry Andric     break;
27860b57cec5SDimitry Andric   case llvm::Triple::mips64el:
27870b57cec5SDimitry Andric     LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
27880b57cec5SDimitry Andric     TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
27890b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
27900b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
27910b57cec5SDimitry Andric     BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
27920b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
27930b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
27940b57cec5SDimitry Andric     break;
27950b57cec5SDimitry Andric   case llvm::Triple::msp430:
27960b57cec5SDimitry Andric     LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs));
27970b57cec5SDimitry Andric     TripleAliases.append(begin(MSP430Triples), end(MSP430Triples));
27980b57cec5SDimitry Andric     break;
27990b57cec5SDimitry Andric   case llvm::Triple::ppc:
28000b57cec5SDimitry Andric     LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
28010b57cec5SDimitry Andric     TripleAliases.append(begin(PPCTriples), end(PPCTriples));
28020b57cec5SDimitry Andric     BiarchLibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));
28030b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(PPC64Triples), end(PPC64Triples));
28040b57cec5SDimitry Andric     break;
2805e8d8bef9SDimitry Andric   case llvm::Triple::ppcle:
2806e8d8bef9SDimitry Andric     LibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));
2807e8d8bef9SDimitry Andric     TripleAliases.append(begin(PPCLETriples), end(PPCLETriples));
2808e8d8bef9SDimitry Andric     BiarchLibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
2809e8d8bef9SDimitry Andric     BiarchTripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
2810e8d8bef9SDimitry Andric     break;
28110b57cec5SDimitry Andric   case llvm::Triple::ppc64:
28120b57cec5SDimitry Andric     LibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));
28130b57cec5SDimitry Andric     TripleAliases.append(begin(PPC64Triples), end(PPC64Triples));
28140b57cec5SDimitry Andric     BiarchLibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
28150b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(PPCTriples), end(PPCTriples));
28160b57cec5SDimitry Andric     break;
28170b57cec5SDimitry Andric   case llvm::Triple::ppc64le:
28180b57cec5SDimitry Andric     LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
28190b57cec5SDimitry Andric     TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
2820e8d8bef9SDimitry Andric     BiarchLibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));
2821e8d8bef9SDimitry Andric     BiarchTripleAliases.append(begin(PPCLETriples), end(PPCLETriples));
28220b57cec5SDimitry Andric     break;
28230b57cec5SDimitry Andric   case llvm::Triple::riscv32:
28240b57cec5SDimitry Andric     LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
28250b57cec5SDimitry Andric     TripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));
28260b57cec5SDimitry Andric     BiarchLibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));
28270b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));
28280b57cec5SDimitry Andric     break;
28290b57cec5SDimitry Andric   case llvm::Triple::riscv64:
28300b57cec5SDimitry Andric     LibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));
28310b57cec5SDimitry Andric     TripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));
28320b57cec5SDimitry Andric     BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
28330b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));
28340b57cec5SDimitry Andric     break;
28350b57cec5SDimitry Andric   case llvm::Triple::sparc:
28360b57cec5SDimitry Andric   case llvm::Triple::sparcel:
28370b57cec5SDimitry Andric     LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
28380b57cec5SDimitry Andric     TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));
28390b57cec5SDimitry Andric     BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));
28400b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));
28410b57cec5SDimitry Andric     break;
28420b57cec5SDimitry Andric   case llvm::Triple::sparcv9:
28430b57cec5SDimitry Andric     LibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));
28440b57cec5SDimitry Andric     TripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));
28450b57cec5SDimitry Andric     BiarchLibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
28460b57cec5SDimitry Andric     BiarchTripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));
28470b57cec5SDimitry Andric     break;
28480b57cec5SDimitry Andric   case llvm::Triple::systemz:
28490b57cec5SDimitry Andric     LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs));
28500b57cec5SDimitry Andric     TripleAliases.append(begin(SystemZTriples), end(SystemZTriples));
28510b57cec5SDimitry Andric     break;
28520b57cec5SDimitry Andric   default:
28530b57cec5SDimitry Andric     // By default, just rely on the standard lib directories and the original
28540b57cec5SDimitry Andric     // triple.
28550b57cec5SDimitry Andric     break;
28560b57cec5SDimitry Andric   }
28570b57cec5SDimitry Andric 
28580b57cec5SDimitry Andric   // Also include the multiarch variant if it's different.
28590b57cec5SDimitry Andric   if (TargetTriple.str() != BiarchTriple.str())
28600b57cec5SDimitry Andric     BiarchTripleAliases.push_back(BiarchTriple.str());
28610b57cec5SDimitry Andric }
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
28640b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, const ArgList &Args,
28650b57cec5SDimitry Andric     StringRef Path, bool NeedsBiarchSuffix) {
28660b57cec5SDimitry Andric   llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
28670b57cec5SDimitry Andric   DetectedMultilibs Detected;
28680b57cec5SDimitry Andric 
28690b57cec5SDimitry Andric   // Android standalone toolchain could have multilibs for ARM and Thumb.
28700b57cec5SDimitry Andric   // Debian mips multilibs behave more like the rest of the biarch ones,
28710b57cec5SDimitry Andric   // so handle them there
28720b57cec5SDimitry Andric   if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
28730b57cec5SDimitry Andric     // It should also work without multilibs in a simplified toolchain.
28740b57cec5SDimitry Andric     findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
287581ad6265SDimitry Andric   } else if (TargetTriple.isCSKY()) {
287681ad6265SDimitry Andric     findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);
28770b57cec5SDimitry Andric   } else if (TargetTriple.isMIPS()) {
28780b57cec5SDimitry Andric     if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
28790b57cec5SDimitry Andric       return false;
28800b57cec5SDimitry Andric   } else if (TargetTriple.isRISCV()) {
28810b57cec5SDimitry Andric     findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
28820b57cec5SDimitry Andric   } else if (isMSP430(TargetArch)) {
28830b57cec5SDimitry Andric     findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);
28840b57cec5SDimitry Andric   } else if (TargetArch == llvm::Triple::avr) {
28850b57cec5SDimitry Andric     // AVR has no multilibs.
28860b57cec5SDimitry Andric   } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
28870b57cec5SDimitry Andric                                   NeedsBiarchSuffix, Detected)) {
28880b57cec5SDimitry Andric     return false;
28890b57cec5SDimitry Andric   }
28900b57cec5SDimitry Andric 
28910b57cec5SDimitry Andric   Multilibs = Detected.Multilibs;
289206c3fb27SDimitry Andric   SelectedMultilib = Detected.SelectedMultilibs.empty()
289306c3fb27SDimitry Andric                          ? Multilib()
289406c3fb27SDimitry Andric                          : Detected.SelectedMultilibs.back();
28950b57cec5SDimitry Andric   BiarchSibling = Detected.BiarchSibling;
28960b57cec5SDimitry Andric 
28970b57cec5SDimitry Andric   return true;
28980b57cec5SDimitry Andric }
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
29010b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, const ArgList &Args,
29020b57cec5SDimitry Andric     const std::string &LibDir, StringRef CandidateTriple,
2903e8d8bef9SDimitry Andric     bool NeedsBiarchSuffix, bool GCCDirExists, bool GCCCrossDirExists) {
29040b57cec5SDimitry Andric   // Locations relative to the system lib directory where GCC's triple-specific
29050b57cec5SDimitry Andric   // directories might reside.
29060b57cec5SDimitry Andric   struct GCCLibSuffix {
29070b57cec5SDimitry Andric     // Path from system lib directory to GCC triple-specific directory.
29080b57cec5SDimitry Andric     std::string LibSuffix;
29090b57cec5SDimitry Andric     // Path from GCC triple-specific directory back to system lib directory.
29100b57cec5SDimitry Andric     // This is one '..' component per component in LibSuffix.
29110b57cec5SDimitry Andric     StringRef ReversePath;
29120b57cec5SDimitry Andric     // Whether this library suffix is relevant for the triple.
29130b57cec5SDimitry Andric     bool Active;
29140b57cec5SDimitry Andric   } Suffixes[] = {
29150b57cec5SDimitry Andric       // This is the normal place.
2916e8d8bef9SDimitry Andric       {"gcc/" + CandidateTriple.str(), "../..", GCCDirExists},
29170b57cec5SDimitry Andric 
29180b57cec5SDimitry Andric       // Debian puts cross-compilers in gcc-cross.
2919e8d8bef9SDimitry Andric       {"gcc-cross/" + CandidateTriple.str(), "../..", GCCCrossDirExists},
29200b57cec5SDimitry Andric 
29210b57cec5SDimitry Andric       // The Freescale PPC SDK has the gcc libraries in
29220b57cec5SDimitry Andric       // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do
29230b57cec5SDimitry Andric       // this on Freescale triples, though, since some systems put a *lot* of
29240b57cec5SDimitry Andric       // files in that location, not just GCC installation data.
29250b57cec5SDimitry Andric       {CandidateTriple.str(), "..",
29260b57cec5SDimitry Andric        TargetTriple.getVendor() == llvm::Triple::Freescale ||
2927fe6060f1SDimitry Andric            TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
29280b57cec5SDimitry Andric 
29290b57cec5SDimitry Andric   for (auto &Suffix : Suffixes) {
29300b57cec5SDimitry Andric     if (!Suffix.Active)
29310b57cec5SDimitry Andric       continue;
29320b57cec5SDimitry Andric 
29330b57cec5SDimitry Andric     StringRef LibSuffix = Suffix.LibSuffix;
29340b57cec5SDimitry Andric     std::error_code EC;
29350b57cec5SDimitry Andric     for (llvm::vfs::directory_iterator
29360b57cec5SDimitry Andric              LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),
29370b57cec5SDimitry Andric              LE;
29380b57cec5SDimitry Andric          !EC && LI != LE; LI = LI.increment(EC)) {
29390b57cec5SDimitry Andric       StringRef VersionText = llvm::sys::path::filename(LI->path());
29400b57cec5SDimitry Andric       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
29410b57cec5SDimitry Andric       if (CandidateVersion.Major != -1) // Filter obviously bad entries.
29425ffd83dbSDimitry Andric         if (!CandidateGCCInstallPaths.insert(std::string(LI->path())).second)
29430b57cec5SDimitry Andric           continue; // Saw this path before; no need to look at it again.
29440b57cec5SDimitry Andric       if (CandidateVersion.isOlderThan(4, 1, 1))
29450b57cec5SDimitry Andric         continue;
29460b57cec5SDimitry Andric       if (CandidateVersion <= Version)
29470b57cec5SDimitry Andric         continue;
29480b57cec5SDimitry Andric 
29490b57cec5SDimitry Andric       if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
29500b57cec5SDimitry Andric                                NeedsBiarchSuffix))
29510b57cec5SDimitry Andric         continue;
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric       Version = CandidateVersion;
29540b57cec5SDimitry Andric       GCCTriple.setTriple(CandidateTriple);
29550b57cec5SDimitry Andric       // FIXME: We hack together the directory name here instead of
29560b57cec5SDimitry Andric       // using LI to ensure stable path separators across Windows and
29570b57cec5SDimitry Andric       // Linux.
29580b57cec5SDimitry Andric       GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
29590b57cec5SDimitry Andric       GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
29600b57cec5SDimitry Andric       IsValid = true;
29610b57cec5SDimitry Andric     }
29620b57cec5SDimitry Andric   }
29630b57cec5SDimitry Andric }
29640b57cec5SDimitry Andric 
29650b57cec5SDimitry Andric bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
29660b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, const ArgList &Args,
29670b57cec5SDimitry Andric     const SmallVectorImpl<StringRef> &CandidateTriples,
29680b57cec5SDimitry Andric     const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
296981ad6265SDimitry Andric   if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))
2970e8d8bef9SDimitry Andric     return false;
2971e8d8bef9SDimitry Andric 
29720b57cec5SDimitry Andric   for (StringRef CandidateTriple : CandidateTriples) {
29730b57cec5SDimitry Andric     if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))
29740b57cec5SDimitry Andric       return true;
29750b57cec5SDimitry Andric   }
29760b57cec5SDimitry Andric 
29770b57cec5SDimitry Andric   for (StringRef CandidateTriple : CandidateBiarchTriples) {
29780b57cec5SDimitry Andric     if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true))
29790b57cec5SDimitry Andric       return true;
29800b57cec5SDimitry Andric   }
29810b57cec5SDimitry Andric   return false;
29820b57cec5SDimitry Andric }
29830b57cec5SDimitry Andric 
29840b57cec5SDimitry Andric bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
29850b57cec5SDimitry Andric     const llvm::Triple &TargetTriple, const ArgList &Args,
29860b57cec5SDimitry Andric     StringRef CandidateTriple, bool NeedsBiarchSuffix) {
29870b57cec5SDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
298881ad6265SDimitry Andric       D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,
298981ad6265SDimitry Andric                                          "/config-" + CandidateTriple.str()));
29900b57cec5SDimitry Andric   if (File) {
29910b57cec5SDimitry Andric     SmallVector<StringRef, 2> Lines;
29920b57cec5SDimitry Andric     File.get()->getBuffer().split(Lines, "\n");
29930b57cec5SDimitry Andric     for (StringRef Line : Lines) {
29940b57cec5SDimitry Andric       Line = Line.trim();
29950b57cec5SDimitry Andric       // CURRENT=triple-version
29960b57cec5SDimitry Andric       if (!Line.consume_front("CURRENT="))
29970b57cec5SDimitry Andric         continue;
29980b57cec5SDimitry Andric       // Process the config file pointed to by CURRENT.
29990b57cec5SDimitry Andric       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
300081ad6265SDimitry Andric           D.getVFS().getBufferForFile(
300181ad6265SDimitry Andric               concat(D.SysRoot, GentooConfigDir, "/" + Line));
30020b57cec5SDimitry Andric       std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
30030b57cec5SDimitry Andric       // List of paths to scan for libraries.
30040b57cec5SDimitry Andric       SmallVector<StringRef, 4> GentooScanPaths;
30050b57cec5SDimitry Andric       // Scan the Config file to find installed GCC libraries path.
30060b57cec5SDimitry Andric       // Typical content of the GCC config file:
30070b57cec5SDimitry Andric       // LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x:/usr/lib/gcc/
30080b57cec5SDimitry Andric       // (continued from previous line) x86_64-pc-linux-gnu/4.9.x/32"
30090b57cec5SDimitry Andric       // MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/man"
30100b57cec5SDimitry Andric       // INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/info"
30110b57cec5SDimitry Andric       // STDCXX_INCDIR="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4"
30120b57cec5SDimitry Andric       // We are looking for the paths listed in LDPATH=... .
30130b57cec5SDimitry Andric       if (ConfigFile) {
30140b57cec5SDimitry Andric         SmallVector<StringRef, 2> ConfigLines;
30150b57cec5SDimitry Andric         ConfigFile.get()->getBuffer().split(ConfigLines, "\n");
30160b57cec5SDimitry Andric         for (StringRef ConfLine : ConfigLines) {
30170b57cec5SDimitry Andric           ConfLine = ConfLine.trim();
30180b57cec5SDimitry Andric           if (ConfLine.consume_front("LDPATH=")) {
30190b57cec5SDimitry Andric             // Drop '"' from front and back if present.
30200b57cec5SDimitry Andric             ConfLine.consume_back("\"");
30210b57cec5SDimitry Andric             ConfLine.consume_front("\"");
30220b57cec5SDimitry Andric             // Get all paths sperated by ':'
30230b57cec5SDimitry Andric             ConfLine.split(GentooScanPaths, ':', -1, /*AllowEmpty*/ false);
30240b57cec5SDimitry Andric           }
30250b57cec5SDimitry Andric         }
30260b57cec5SDimitry Andric       }
30270b57cec5SDimitry Andric       // Test the path based on the version in /etc/env.d/gcc/config-{tuple}.
30280b57cec5SDimitry Andric       std::string basePath = "/usr/lib/gcc/" + ActiveVersion.first.str() + "/"
30290b57cec5SDimitry Andric           + ActiveVersion.second.str();
30300b57cec5SDimitry Andric       GentooScanPaths.push_back(StringRef(basePath));
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric       // Scan all paths for GCC libraries.
30330b57cec5SDimitry Andric       for (const auto &GentooScanPath : GentooScanPaths) {
303481ad6265SDimitry Andric         std::string GentooPath = concat(D.SysRoot, GentooScanPath);
30350b57cec5SDimitry Andric         if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
30360b57cec5SDimitry Andric           if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
30370b57cec5SDimitry Andric                                    NeedsBiarchSuffix))
30380b57cec5SDimitry Andric             continue;
30390b57cec5SDimitry Andric 
30400b57cec5SDimitry Andric           Version = GCCVersion::Parse(ActiveVersion.second);
30410b57cec5SDimitry Andric           GCCInstallPath = GentooPath;
30420b57cec5SDimitry Andric           GCCParentLibPath = GentooPath + std::string("/../../..");
30430b57cec5SDimitry Andric           GCCTriple.setTriple(ActiveVersion.first);
30440b57cec5SDimitry Andric           IsValid = true;
30450b57cec5SDimitry Andric           return true;
30460b57cec5SDimitry Andric         }
30470b57cec5SDimitry Andric       }
30480b57cec5SDimitry Andric     }
30490b57cec5SDimitry Andric   }
30500b57cec5SDimitry Andric 
30510b57cec5SDimitry Andric   return false;
30520b57cec5SDimitry Andric }
30530b57cec5SDimitry Andric 
30540b57cec5SDimitry Andric Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
30550b57cec5SDimitry Andric                          const ArgList &Args)
30560b57cec5SDimitry Andric     : ToolChain(D, Triple, Args), GCCInstallation(D),
30575ffd83dbSDimitry Andric       CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {
30580b57cec5SDimitry Andric   getProgramPaths().push_back(getDriver().Dir);
30590b57cec5SDimitry Andric }
30600b57cec5SDimitry Andric 
30610b57cec5SDimitry Andric Generic_GCC::~Generic_GCC() {}
30620b57cec5SDimitry Andric 
30630b57cec5SDimitry Andric Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
30640b57cec5SDimitry Andric   switch (AC) {
30650b57cec5SDimitry Andric   case Action::PreprocessJobClass:
30660b57cec5SDimitry Andric     if (!Preprocess)
30670b57cec5SDimitry Andric       Preprocess.reset(new clang::driver::tools::gcc::Preprocessor(*this));
30680b57cec5SDimitry Andric     return Preprocess.get();
30690b57cec5SDimitry Andric   case Action::CompileJobClass:
30700b57cec5SDimitry Andric     if (!Compile)
30710b57cec5SDimitry Andric       Compile.reset(new tools::gcc::Compiler(*this));
30720b57cec5SDimitry Andric     return Compile.get();
30730b57cec5SDimitry Andric   default:
30740b57cec5SDimitry Andric     return ToolChain::getTool(AC);
30750b57cec5SDimitry Andric   }
30760b57cec5SDimitry Andric }
30770b57cec5SDimitry Andric 
30780b57cec5SDimitry Andric Tool *Generic_GCC::buildAssembler() const {
30790b57cec5SDimitry Andric   return new tools::gnutools::Assembler(*this);
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric 
30820b57cec5SDimitry Andric Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
30830b57cec5SDimitry Andric 
30840b57cec5SDimitry Andric void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
30850b57cec5SDimitry Andric   // Print the information about how we detected the GCC installation.
30860b57cec5SDimitry Andric   GCCInstallation.print(OS);
308706c3fb27SDimitry Andric   CudaInstallation->print(OS);
308806c3fb27SDimitry Andric   RocmInstallation->print(OS);
30890b57cec5SDimitry Andric }
30900b57cec5SDimitry Andric 
3091bdd1243dSDimitry Andric ToolChain::UnwindTableLevel
3092bdd1243dSDimitry Andric Generic_GCC::getDefaultUnwindTableLevel(const ArgList &Args) const {
3093e8d8bef9SDimitry Andric   switch (getArch()) {
3094e8d8bef9SDimitry Andric   case llvm::Triple::aarch64:
30955f757f3fSDimitry Andric   case llvm::Triple::aarch64_be:
3096e8d8bef9SDimitry Andric   case llvm::Triple::ppc:
3097e8d8bef9SDimitry Andric   case llvm::Triple::ppcle:
3098e8d8bef9SDimitry Andric   case llvm::Triple::ppc64:
3099e8d8bef9SDimitry Andric   case llvm::Triple::ppc64le:
310006c3fb27SDimitry Andric   case llvm::Triple::riscv32:
310106c3fb27SDimitry Andric   case llvm::Triple::riscv64:
3102349cc55cSDimitry Andric   case llvm::Triple::x86:
3103e8d8bef9SDimitry Andric   case llvm::Triple::x86_64:
3104bdd1243dSDimitry Andric     return UnwindTableLevel::Asynchronous;
3105e8d8bef9SDimitry Andric   default:
3106bdd1243dSDimitry Andric     return UnwindTableLevel::None;
3107e8d8bef9SDimitry Andric   }
31080b57cec5SDimitry Andric }
31090b57cec5SDimitry Andric 
31100b57cec5SDimitry Andric bool Generic_GCC::isPICDefault() const {
31110b57cec5SDimitry Andric   switch (getArch()) {
31120b57cec5SDimitry Andric   case llvm::Triple::x86_64:
31130b57cec5SDimitry Andric     return getTriple().isOSWindows();
31140b57cec5SDimitry Andric   case llvm::Triple::mips64:
31150b57cec5SDimitry Andric   case llvm::Triple::mips64el:
31160b57cec5SDimitry Andric     return true;
31170b57cec5SDimitry Andric   default:
31180b57cec5SDimitry Andric     return false;
31190b57cec5SDimitry Andric   }
31200b57cec5SDimitry Andric }
31210b57cec5SDimitry Andric 
3122349cc55cSDimitry Andric bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const {
3123349cc55cSDimitry Andric   return false;
3124349cc55cSDimitry Andric }
31250b57cec5SDimitry Andric 
31260b57cec5SDimitry Andric bool Generic_GCC::isPICDefaultForced() const {
31270b57cec5SDimitry Andric   return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
31280b57cec5SDimitry Andric }
31290b57cec5SDimitry Andric 
31300b57cec5SDimitry Andric bool Generic_GCC::IsIntegratedAssemblerDefault() const {
31310b57cec5SDimitry Andric   switch (getTriple().getArch()) {
313206c3fb27SDimitry Andric   case llvm::Triple::nvptx:
313306c3fb27SDimitry Andric   case llvm::Triple::nvptx64:
313406c3fb27SDimitry Andric   case llvm::Triple::xcore:
31350b57cec5SDimitry Andric     return false;
313606c3fb27SDimitry Andric   default:
31375f757f3fSDimitry Andric     return true;
31380b57cec5SDimitry Andric   }
31390b57cec5SDimitry Andric }
31400b57cec5SDimitry Andric 
31415ffd83dbSDimitry Andric void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {
31425ffd83dbSDimitry Andric   // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
31435ffd83dbSDimitry Andric   // least) put various tools in a triple-prefixed directory off of the parent
31445ffd83dbSDimitry Andric   // of the GCC installation. We use the GCC triple here to ensure that we end
31455ffd83dbSDimitry Andric   // up with tools that support the same amount of cross compiling as the
31465ffd83dbSDimitry Andric   // detected GCC installation. For example, if we find a GCC installation
31475ffd83dbSDimitry Andric   // targeting x86_64, but it is a bi-arch GCC installation, it can also be
31485ffd83dbSDimitry Andric   // used to target i386.
31495ffd83dbSDimitry Andric   if (GCCInstallation.isValid()) {
31505ffd83dbSDimitry Andric     PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
31515ffd83dbSDimitry Andric                            GCCInstallation.getTriple().str() + "/bin")
31525ffd83dbSDimitry Andric                          .str());
31535ffd83dbSDimitry Andric   }
31545ffd83dbSDimitry Andric }
31555ffd83dbSDimitry Andric 
31565ffd83dbSDimitry Andric void Generic_GCC::AddMultilibPaths(const Driver &D,
31575ffd83dbSDimitry Andric                                    const std::string &SysRoot,
31585ffd83dbSDimitry Andric                                    const std::string &OSLibDir,
31595ffd83dbSDimitry Andric                                    const std::string &MultiarchTriple,
31605ffd83dbSDimitry Andric                                    path_list &Paths) {
31615ffd83dbSDimitry Andric   // Add the multilib suffixed paths where they are available.
31625ffd83dbSDimitry Andric   if (GCCInstallation.isValid()) {
316306c3fb27SDimitry Andric     assert(!SelectedMultilibs.empty());
31645ffd83dbSDimitry Andric     const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
31655ffd83dbSDimitry Andric     const std::string &LibPath =
31665ffd83dbSDimitry Andric         std::string(GCCInstallation.getParentLibPath());
31675ffd83dbSDimitry Andric 
31685ffd83dbSDimitry Andric     // Sourcery CodeBench MIPS toolchain holds some libraries under
31695ffd83dbSDimitry Andric     // a biarch-like suffix of the GCC installation.
3170fe6060f1SDimitry Andric     if (const auto &PathsCallback = Multilibs.filePathsCallback())
317106c3fb27SDimitry Andric       for (const auto &Path : PathsCallback(SelectedMultilibs.back()))
3172fe6060f1SDimitry Andric         addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);
3173fe6060f1SDimitry Andric 
3174fe6060f1SDimitry Andric     // Add lib/gcc/$triple/$version, with an optional /multilib suffix.
317506c3fb27SDimitry Andric     addPathIfExists(D,
317606c3fb27SDimitry Andric                     GCCInstallation.getInstallPath() +
317706c3fb27SDimitry Andric                         SelectedMultilibs.back().gccSuffix(),
31785ffd83dbSDimitry Andric                     Paths);
31795ffd83dbSDimitry Andric 
318081ad6265SDimitry Andric     // Add lib/gcc/$triple/$libdir
318181ad6265SDimitry Andric     // For GCC built with --enable-version-specific-runtime-libs.
318281ad6265SDimitry Andric     addPathIfExists(D, GCCInstallation.getInstallPath() + "/../" + OSLibDir,
318381ad6265SDimitry Andric                     Paths);
318481ad6265SDimitry Andric 
31855ffd83dbSDimitry Andric     // GCC cross compiling toolchains will install target libraries which ship
31865ffd83dbSDimitry Andric     // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
31875ffd83dbSDimitry Andric     // any part of the GCC installation in
31885ffd83dbSDimitry Andric     // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
31895ffd83dbSDimitry Andric     // debatable, but is the reality today. We need to search this tree even
31905ffd83dbSDimitry Andric     // when we have a sysroot somewhere else. It is the responsibility of
31915ffd83dbSDimitry Andric     // whomever is doing the cross build targeting a sysroot using a GCC
31925ffd83dbSDimitry Andric     // installation that is *not* within the system root to ensure two things:
31935ffd83dbSDimitry Andric     //
31945ffd83dbSDimitry Andric     //  1) Any DSOs that are linked in from this tree or from the install path
31955ffd83dbSDimitry Andric     //     above must be present on the system root and found via an
31965ffd83dbSDimitry Andric     //     appropriate rpath.
31975ffd83dbSDimitry Andric     //  2) There must not be libraries installed into
31985ffd83dbSDimitry Andric     //     <prefix>/<triple>/<libdir> unless they should be preferred over
31995ffd83dbSDimitry Andric     //     those within the system root.
32005ffd83dbSDimitry Andric     //
32015ffd83dbSDimitry Andric     // Note that this matches the GCC behavior. See the below comment for where
32025ffd83dbSDimitry Andric     // Clang diverges from GCC's behavior.
32035ffd83dbSDimitry Andric     addPathIfExists(D,
32045ffd83dbSDimitry Andric                     LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
320506c3fb27SDimitry Andric                         SelectedMultilibs.back().osSuffix(),
32065ffd83dbSDimitry Andric                     Paths);
32075ffd83dbSDimitry Andric 
32085ffd83dbSDimitry Andric     // If the GCC installation we found is inside of the sysroot, we want to
32095ffd83dbSDimitry Andric     // prefer libraries installed in the parent prefix of the GCC installation.
32105ffd83dbSDimitry Andric     // It is important to *not* use these paths when the GCC installation is
32115ffd83dbSDimitry Andric     // outside of the system root as that can pick up unintended libraries.
32125ffd83dbSDimitry Andric     // This usually happens when there is an external cross compiler on the
32135ffd83dbSDimitry Andric     // host system, and a more minimal sysroot available that is the target of
32145ffd83dbSDimitry Andric     // the cross. Note that GCC does include some of these directories in some
32155ffd83dbSDimitry Andric     // configurations but this seems somewhere between questionable and simply
32165ffd83dbSDimitry Andric     // a bug.
32175f757f3fSDimitry Andric     if (StringRef(LibPath).starts_with(SysRoot))
32185ffd83dbSDimitry Andric       addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
32195ffd83dbSDimitry Andric   }
32205ffd83dbSDimitry Andric }
32215ffd83dbSDimitry Andric 
32225ffd83dbSDimitry Andric void Generic_GCC::AddMultiarchPaths(const Driver &D,
32235ffd83dbSDimitry Andric                                     const std::string &SysRoot,
32245ffd83dbSDimitry Andric                                     const std::string &OSLibDir,
32255ffd83dbSDimitry Andric                                     path_list &Paths) {
32265ffd83dbSDimitry Andric   if (GCCInstallation.isValid()) {
32275ffd83dbSDimitry Andric     const std::string &LibPath =
32285ffd83dbSDimitry Andric         std::string(GCCInstallation.getParentLibPath());
32295ffd83dbSDimitry Andric     const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
32305ffd83dbSDimitry Andric     const Multilib &Multilib = GCCInstallation.getMultilib();
32315ffd83dbSDimitry Andric     addPathIfExists(
32325ffd83dbSDimitry Andric         D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),
32335ffd83dbSDimitry Andric                     Paths);
32345ffd83dbSDimitry Andric   }
32355ffd83dbSDimitry Andric }
32365ffd83dbSDimitry Andric 
32375ffd83dbSDimitry Andric void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
32385ffd83dbSDimitry Andric                                          ArgStringList &CC1Args) const {
32395ffd83dbSDimitry Andric   // Add include directories specific to the selected multilib set and multilib.
3240fe6060f1SDimitry Andric   if (!GCCInstallation.isValid())
3241fe6060f1SDimitry Andric     return;
3242fe6060f1SDimitry Andric   // gcc TOOL_INCLUDE_DIR.
3243fe6060f1SDimitry Andric   const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
3244fe6060f1SDimitry Andric   std::string LibPath(GCCInstallation.getParentLibPath());
3245fe6060f1SDimitry Andric   addSystemInclude(DriverArgs, CC1Args,
3246fe6060f1SDimitry Andric                    Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
3247fe6060f1SDimitry Andric 
32485ffd83dbSDimitry Andric   const auto &Callback = Multilibs.includeDirsCallback();
32495ffd83dbSDimitry Andric   if (Callback) {
32505ffd83dbSDimitry Andric     for (const auto &Path : Callback(GCCInstallation.getMultilib()))
3251fe6060f1SDimitry Andric       addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
3252fe6060f1SDimitry Andric                                       GCCInstallation.getInstallPath() + Path);
32535ffd83dbSDimitry Andric   }
32545ffd83dbSDimitry Andric }
32555ffd83dbSDimitry Andric 
32560b57cec5SDimitry Andric void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
32570b57cec5SDimitry Andric                                                ArgStringList &CC1Args) const {
3258fe6060f1SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
3259fe6060f1SDimitry Andric                         options::OPT_nostdlibinc))
32600b57cec5SDimitry Andric     return;
32610b57cec5SDimitry Andric 
32620b57cec5SDimitry Andric   switch (GetCXXStdlibType(DriverArgs)) {
32630b57cec5SDimitry Andric   case ToolChain::CST_Libcxx:
32640b57cec5SDimitry Andric     addLibCxxIncludePaths(DriverArgs, CC1Args);
32650b57cec5SDimitry Andric     break;
32660b57cec5SDimitry Andric 
32670b57cec5SDimitry Andric   case ToolChain::CST_Libstdcxx:
32680b57cec5SDimitry Andric     addLibStdCxxIncludePaths(DriverArgs, CC1Args);
32690b57cec5SDimitry Andric     break;
32700b57cec5SDimitry Andric   }
32710b57cec5SDimitry Andric }
32720b57cec5SDimitry Andric 
32730b57cec5SDimitry Andric void
3274480093f4SDimitry Andric Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
32750b57cec5SDimitry Andric                                    llvm::opt::ArgStringList &CC1Args) const {
3276fe6060f1SDimitry Andric   const Driver &D = getDriver();
3277fe6060f1SDimitry Andric   std::string SysRoot = computeSysRoot();
32785f757f3fSDimitry Andric   if (SysRoot.empty())
32795f757f3fSDimitry Andric     SysRoot = llvm::sys::path::get_separator();
3280fe6060f1SDimitry Andric 
32815f757f3fSDimitry Andric   auto AddIncludePath = [&](StringRef Path, bool TargetDirRequired = false) {
3282fe6060f1SDimitry Andric     std::string Version = detectLibcxxVersion(Path);
3283fe6060f1SDimitry Andric     if (Version.empty())
3284480093f4SDimitry Andric       return false;
3285fe6060f1SDimitry Andric 
3286fe6060f1SDimitry Andric     // First add the per-target include path if it exists.
32875f757f3fSDimitry Andric     bool TargetDirExists = false;
32885f757f3fSDimitry Andric     std::optional<std::string> TargetIncludeDir = getTargetSubDirPath(Path);
32895f757f3fSDimitry Andric     if (TargetIncludeDir) {
32905f757f3fSDimitry Andric       SmallString<128> TargetDir(*TargetIncludeDir);
32915f757f3fSDimitry Andric       llvm::sys::path::append(TargetDir, "c++", Version);
32925f757f3fSDimitry Andric       if (D.getVFS().exists(TargetDir)) {
3293fe6060f1SDimitry Andric         addSystemInclude(DriverArgs, CC1Args, TargetDir);
32945f757f3fSDimitry Andric         TargetDirExists = true;
32955f757f3fSDimitry Andric       }
32965f757f3fSDimitry Andric     }
32975f757f3fSDimitry Andric     if (TargetDirRequired && !TargetDirExists)
32985f757f3fSDimitry Andric       return false;
3299fe6060f1SDimitry Andric 
3300fe6060f1SDimitry Andric     // Second add the generic one.
33015f757f3fSDimitry Andric     SmallString<128> GenericDir(Path);
33025f757f3fSDimitry Andric     llvm::sys::path::append(GenericDir, "c++", Version);
33035f757f3fSDimitry Andric     addSystemInclude(DriverArgs, CC1Args, GenericDir);
3304480093f4SDimitry Andric     return true;
3305480093f4SDimitry Andric   };
3306fe6060f1SDimitry Andric 
33075f757f3fSDimitry Andric   // Android only uses the libc++ headers installed alongside the toolchain if
33085f757f3fSDimitry Andric   // they contain an Android-specific target include path, otherwise they're
33095f757f3fSDimitry Andric   // incompatible with the NDK libraries.
33105f757f3fSDimitry Andric   SmallString<128> DriverIncludeDir(getDriver().Dir);
33115f757f3fSDimitry Andric   llvm::sys::path::append(DriverIncludeDir, "..", "include");
33125f757f3fSDimitry Andric   if (AddIncludePath(DriverIncludeDir,
33135f757f3fSDimitry Andric                      /*TargetDirRequired=*/getTriple().isAndroid()))
3314480093f4SDimitry Andric     return;
3315480093f4SDimitry Andric   // If this is a development, non-installed, clang, libcxx will
3316480093f4SDimitry Andric   // not be found at ../include/c++ but it likely to be found at
3317480093f4SDimitry Andric   // one of the following two locations:
33185f757f3fSDimitry Andric   SmallString<128> UsrLocalIncludeDir(SysRoot);
33195f757f3fSDimitry Andric   llvm::sys::path::append(UsrLocalIncludeDir, "usr", "local", "include");
33205f757f3fSDimitry Andric   if (AddIncludePath(UsrLocalIncludeDir))
3321480093f4SDimitry Andric     return;
33225f757f3fSDimitry Andric   SmallString<128> UsrIncludeDir(SysRoot);
33235f757f3fSDimitry Andric   llvm::sys::path::append(UsrIncludeDir, "usr", "include");
33245f757f3fSDimitry Andric   if (AddIncludePath(UsrIncludeDir))
3325480093f4SDimitry Andric     return;
33260b57cec5SDimitry Andric }
33270b57cec5SDimitry Andric 
3328fe6060f1SDimitry Andric bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
3329fe6060f1SDimitry Andric                                            Twine IncludeSuffix,
3330fe6060f1SDimitry Andric                                            const llvm::opt::ArgList &DriverArgs,
3331fe6060f1SDimitry Andric                                            llvm::opt::ArgStringList &CC1Args,
3332fe6060f1SDimitry Andric                                            bool DetectDebian) const {
3333fe6060f1SDimitry Andric   if (!getVFS().exists(IncludeDir))
33340b57cec5SDimitry Andric     return false;
33350b57cec5SDimitry Andric 
3336fe6060f1SDimitry Andric   // Debian native gcc uses g++-multiarch-incdir.diff which uses
3337fe6060f1SDimitry Andric   // include/x86_64-linux-gnu/c++/10$IncludeSuffix instead of
3338fe6060f1SDimitry Andric   // include/c++/10/x86_64-linux-gnu$IncludeSuffix.
3339fe6060f1SDimitry Andric   std::string Dir = IncludeDir.str();
3340fe6060f1SDimitry Andric   StringRef Include =
3341fe6060f1SDimitry Andric       llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));
3342fe6060f1SDimitry Andric   std::string Path =
3343fe6060f1SDimitry Andric       (Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
3344fe6060f1SDimitry Andric           .str();
3345fe6060f1SDimitry Andric   if (DetectDebian && !getVFS().exists(Path))
3346fe6060f1SDimitry Andric     return false;
33470b57cec5SDimitry Andric 
3348fe6060f1SDimitry Andric   // GPLUSPLUS_INCLUDE_DIR
3349fe6060f1SDimitry Andric   addSystemInclude(DriverArgs, CC1Args, IncludeDir);
3350fe6060f1SDimitry Andric   // GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
3351fe6060f1SDimitry Andric   // include directory.
3352fe6060f1SDimitry Andric   if (DetectDebian)
3353fe6060f1SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Path);
3354fe6060f1SDimitry Andric   else if (!Triple.empty())
33550b57cec5SDimitry Andric     addSystemInclude(DriverArgs, CC1Args,
3356fe6060f1SDimitry Andric                      IncludeDir + "/" + Triple + IncludeSuffix);
3357fe6060f1SDimitry Andric   // GPLUSPLUS_BACKWARD_INCLUDE_DIR
3358fe6060f1SDimitry Andric   addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
33590b57cec5SDimitry Andric   return true;
33600b57cec5SDimitry Andric }
33610b57cec5SDimitry Andric 
3362fe6060f1SDimitry Andric bool Generic_GCC::addGCCLibStdCxxIncludePaths(
3363fe6060f1SDimitry Andric     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3364fe6060f1SDimitry Andric     StringRef DebianMultiarch) const {
3365fe6060f1SDimitry Andric   assert(GCCInstallation.isValid());
3366480093f4SDimitry Andric 
3367480093f4SDimitry Andric   // By default, look for the C++ headers in an include directory adjacent to
3368480093f4SDimitry Andric   // the lib directory of the GCC installation. Note that this is expect to be
3369480093f4SDimitry Andric   // equivalent to '/usr/include/c++/X.Y' in almost all cases.
3370480093f4SDimitry Andric   StringRef LibDir = GCCInstallation.getParentLibPath();
3371480093f4SDimitry Andric   StringRef InstallDir = GCCInstallation.getInstallPath();
3372480093f4SDimitry Andric   StringRef TripleStr = GCCInstallation.getTriple().str();
3373480093f4SDimitry Andric   const Multilib &Multilib = GCCInstallation.getMultilib();
3374480093f4SDimitry Andric   const GCCVersion &Version = GCCInstallation.getVersion();
3375480093f4SDimitry Andric 
3376fe6060f1SDimitry Andric   // Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
3377fe6060f1SDimitry Andric   if (addLibStdCXXIncludePaths(
3378fe6060f1SDimitry Andric           LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
3379fe6060f1SDimitry Andric           TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
3380fe6060f1SDimitry Andric     return true;
3381fe6060f1SDimitry Andric 
338281ad6265SDimitry Andric   // Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
338381ad6265SDimitry Andric   // empty). Like above but for GCC built with
338481ad6265SDimitry Andric   // --enable-version-specific-runtime-libs.
338581ad6265SDimitry Andric   if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
338681ad6265SDimitry Andric                                    Version.Text + "/include/c++/",
338781ad6265SDimitry Andric                                TripleStr, Multilib.includeSuffix(), DriverArgs,
338881ad6265SDimitry Andric                                CC1Args))
338981ad6265SDimitry Andric     return true;
339081ad6265SDimitry Andric 
3391fe6060f1SDimitry Andric   // Detect Debian g++-multiarch-incdir.diff.
3392fe6060f1SDimitry Andric   if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
3393fe6060f1SDimitry Andric                                DebianMultiarch, Multilib.includeSuffix(),
3394fe6060f1SDimitry Andric                                DriverArgs, CC1Args, /*Debian=*/true))
3395fe6060f1SDimitry Andric     return true;
3396fe6060f1SDimitry Andric 
3397fe6060f1SDimitry Andric   // Try /../include/c++/$version (gcc --print-multiarch is empty).
3398fe6060f1SDimitry Andric   if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
3399fe6060f1SDimitry Andric                                TripleStr, Multilib.includeSuffix(), DriverArgs,
3400fe6060f1SDimitry Andric                                CC1Args))
3401480093f4SDimitry Andric     return true;
3402480093f4SDimitry Andric 
3403480093f4SDimitry Andric   // Otherwise, fall back on a bunch of options which don't use multiarch
3404480093f4SDimitry Andric   // layouts for simplicity.
3405480093f4SDimitry Andric   const std::string LibStdCXXIncludePathCandidates[] = {
3406480093f4SDimitry Andric       // Gentoo is weird and places its headers inside the GCC install,
3407480093f4SDimitry Andric       // so if the first attempt to find the headers fails, try these patterns.
3408480093f4SDimitry Andric       InstallDir.str() + "/include/g++-v" + Version.Text,
3409480093f4SDimitry Andric       InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
3410480093f4SDimitry Andric           Version.MinorStr,
3411480093f4SDimitry Andric       InstallDir.str() + "/include/g++-v" + Version.MajorStr,
3412480093f4SDimitry Andric   };
3413480093f4SDimitry Andric 
3414480093f4SDimitry Andric   for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
3415fe6060f1SDimitry Andric     if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
3416480093f4SDimitry Andric                                  Multilib.includeSuffix(), DriverArgs, CC1Args))
3417480093f4SDimitry Andric       return true;
3418480093f4SDimitry Andric   }
3419480093f4SDimitry Andric   return false;
3420480093f4SDimitry Andric }
3421480093f4SDimitry Andric 
3422480093f4SDimitry Andric void
3423480093f4SDimitry Andric Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
3424480093f4SDimitry Andric                                       llvm::opt::ArgStringList &CC1Args) const {
3425fe6060f1SDimitry Andric   if (GCCInstallation.isValid()) {
3426fe6060f1SDimitry Andric     addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
3427fe6060f1SDimitry Andric                                 GCCInstallation.getTriple().str());
3428fe6060f1SDimitry Andric   }
3429480093f4SDimitry Andric }
3430480093f4SDimitry Andric 
34310b57cec5SDimitry Andric llvm::opt::DerivedArgList *
34320b57cec5SDimitry Andric Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,
34330b57cec5SDimitry Andric                            Action::OffloadKind DeviceOffloadKind) const {
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric   // If this tool chain is used for an OpenMP offloading device we have to make
34360b57cec5SDimitry Andric   // sure we always generate a shared library regardless of the commands the
34370b57cec5SDimitry Andric   // user passed to the host. This is required because the runtime library
34380b57cec5SDimitry Andric   // is required to load the device image dynamically at run time.
34390b57cec5SDimitry Andric   if (DeviceOffloadKind == Action::OFK_OpenMP) {
34400b57cec5SDimitry Andric     DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
34410b57cec5SDimitry Andric     const OptTable &Opts = getDriver().getOpts();
34420b57cec5SDimitry Andric 
34430b57cec5SDimitry Andric     // Request the shared library. Given that these options are decided
34440b57cec5SDimitry Andric     // implicitly, they do not refer to any base argument.
34450b57cec5SDimitry Andric     DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_shared));
34460b57cec5SDimitry Andric     DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_fPIC));
34470b57cec5SDimitry Andric 
34480b57cec5SDimitry Andric     // Filter all the arguments we don't care passing to the offloading
34490b57cec5SDimitry Andric     // toolchain as they can mess up with the creation of a shared library.
34500b57cec5SDimitry Andric     for (auto *A : Args) {
34510b57cec5SDimitry Andric       switch ((options::ID)A->getOption().getID()) {
34520b57cec5SDimitry Andric       default:
34530b57cec5SDimitry Andric         DAL->append(A);
34540b57cec5SDimitry Andric         break;
34550b57cec5SDimitry Andric       case options::OPT_shared:
34560b57cec5SDimitry Andric       case options::OPT_dynamic:
34570b57cec5SDimitry Andric       case options::OPT_static:
34580b57cec5SDimitry Andric       case options::OPT_fPIC:
34590b57cec5SDimitry Andric       case options::OPT_fno_PIC:
34600b57cec5SDimitry Andric       case options::OPT_fpic:
34610b57cec5SDimitry Andric       case options::OPT_fno_pic:
34620b57cec5SDimitry Andric       case options::OPT_fPIE:
34630b57cec5SDimitry Andric       case options::OPT_fno_PIE:
34640b57cec5SDimitry Andric       case options::OPT_fpie:
34650b57cec5SDimitry Andric       case options::OPT_fno_pie:
34660b57cec5SDimitry Andric         break;
34670b57cec5SDimitry Andric       }
34680b57cec5SDimitry Andric     }
34690b57cec5SDimitry Andric     return DAL;
34700b57cec5SDimitry Andric   }
34710b57cec5SDimitry Andric   return nullptr;
34720b57cec5SDimitry Andric }
34730b57cec5SDimitry Andric 
34740b57cec5SDimitry Andric void Generic_ELF::anchor() {}
34750b57cec5SDimitry Andric 
34760b57cec5SDimitry Andric void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
34770b57cec5SDimitry Andric                                         ArgStringList &CC1Args,
34780b57cec5SDimitry Andric                                         Action::OffloadKind) const {
3479480093f4SDimitry Andric   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
3480480093f4SDimitry Andric                           options::OPT_fno_use_init_array, true))
3481480093f4SDimitry Andric     CC1Args.push_back("-fno-use-init-array");
34820b57cec5SDimitry Andric }
3483