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
forwardToGCC(const Option & O)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.
normalizeCPUNamesForAssembler(const ArgList & Args,ArgStringList & CmdArgs)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
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const690b57cec5SDimitry 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
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const1860b57cec5SDimitry Andric void tools::gcc::Preprocessor::RenderExtraToolArgs(
1870b57cec5SDimitry Andric const JobAction &JA, ArgStringList &CmdArgs) const {
1880b57cec5SDimitry Andric CmdArgs.push_back("-E");
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const1910b57cec5SDimitry 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
RenderExtraToolArgs(const JobAction & JA,ArgStringList & CmdArgs) const2190b57cec5SDimitry 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
getLDMOption(const llvm::Triple & T,const ArgList & Args)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
getStaticPIE(const ArgList & Args,const ToolChain & TC)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
getStatic(const ArgList & Args)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
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const3135ffd83dbSDimitry 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
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const3570b57cec5SDimitry 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
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const6830b57cec5SDimitry 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:
FilterNonExistent(StringRef Base,StringRef File,llvm::vfs::FileSystem & VFS)10030b57cec5SDimitry Andric FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)
10040b57cec5SDimitry Andric : Base(Base), File(File), VFS(VFS) {}
operator ()(const Multilib & M)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
isSoftFloatABI(const ArgList & Args)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
isArmOrThumbArch(llvm::Triple::ArchType Arch)10220b57cec5SDimitry Andric static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {
10230b57cec5SDimitry Andric return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric
isMipsEL(llvm::Triple::ArchType Arch)10260b57cec5SDimitry Andric static bool isMipsEL(llvm::Triple::ArchType Arch) {
10270b57cec5SDimitry Andric return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
10280b57cec5SDimitry Andric }
10290b57cec5SDimitry Andric
isMips16(const ArgList & Args)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
isMicroMips(const ArgList & Args)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
isMSP430(llvm::Triple::ArchType Arch)10400b57cec5SDimitry Andric static bool isMSP430(llvm::Triple::ArchType Arch) {
10410b57cec5SDimitry Andric return Arch == llvm::Triple::msp430;
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric
findMipsCsMultilibs(const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)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
findMipsAndroidMultilibs(llvm::vfs::FileSystem & VFS,StringRef Path,const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)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
findMipsMuslMultilibs(const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)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
findMipsMtiMultilibs(const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)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
findMipsImgMultilibs(const Multilib::flags_list & Flags,FilterNonExistent & NonExistent,DetectedMultilibs & Result)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
findMIPSMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
findAndroidArmMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
findMSP430Multilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
findCSKYMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
selectRISCVMultilib(const MultilibSet & RISCVMultilibSet,StringRef Arch,const Multilib::flags_list & Flags,llvm::SmallVectorImpl<Multilib> & SelectedMultilibs)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
findRISCVBareMetalMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
findRISCVMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,DetectedMultilibs & Result)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
findBiarchMultilibs(const Driver & D,const llvm::Triple & TargetTriple,StringRef Path,const ArgList & Args,bool NeedsBiarchSuffix,DetectedMultilibs & Result)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.
isOlderThan(int RHSMajor,int RHSMinor,int RHSPatch,StringRef RHSPatchSuffix) const20770b57cec5SDimitry 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*/
Parse(StringRef VersionText)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
getGCCToolchainDir(const ArgList & Args,llvm::StringRef SysRoot)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.
init(const llvm::Triple & TargetTriple,const ArgList & Args)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
print(raw_ostream & OS) const23580b57cec5SDimitry 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
getBiarchSibling(Multilib & M) const23720b57cec5SDimitry 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
AddDefaultGCCPrefixes(const llvm::Triple & TargetTriple,SmallVectorImpl<std::string> & Prefixes,StringRef SysRoot)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
CollectLibDirsAndTriples(const llvm::Triple & TargetTriple,const llvm::Triple & BiarchTriple,SmallVectorImpl<StringRef> & LibDirs,SmallVectorImpl<StringRef> & TripleAliases,SmallVectorImpl<StringRef> & BiarchLibDirs,SmallVectorImpl<StringRef> & BiarchTripleAliases)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
ScanGCCForMultilibs(const llvm::Triple & TargetTriple,const ArgList & Args,StringRef Path,bool NeedsBiarchSuffix)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
ScanLibDirForGCCTriple(const llvm::Triple & TargetTriple,const ArgList & Args,const std::string & LibDir,StringRef CandidateTriple,bool NeedsBiarchSuffix,bool GCCDirExists,bool GCCCrossDirExists)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
ScanGentooConfigs(const llvm::Triple & TargetTriple,const ArgList & Args,const SmallVectorImpl<StringRef> & CandidateTriples,const SmallVectorImpl<StringRef> & CandidateBiarchTriples)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
ScanGentooGccConfig(const llvm::Triple & TargetTriple,const ArgList & Args,StringRef CandidateTriple,bool NeedsBiarchSuffix)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
Generic_GCC(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)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
~Generic_GCC()30610b57cec5SDimitry Andric Generic_GCC::~Generic_GCC() {}
30620b57cec5SDimitry Andric
getTool(Action::ActionClass AC) const30630b57cec5SDimitry 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
buildAssembler() const30780b57cec5SDimitry Andric Tool *Generic_GCC::buildAssembler() const {
30790b57cec5SDimitry Andric return new tools::gnutools::Assembler(*this);
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric
buildLinker() const30820b57cec5SDimitry Andric Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
30830b57cec5SDimitry Andric
printVerboseInfo(raw_ostream & OS) const30840b57cec5SDimitry 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
getDefaultUnwindTableLevel(const ArgList & Args) const3092bdd1243dSDimitry 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
isPICDefault() const31100b57cec5SDimitry 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
isPIEDefault(const llvm::opt::ArgList & Args) const3122349cc55cSDimitry Andric bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const {
3123349cc55cSDimitry Andric return false;
3124349cc55cSDimitry Andric }
31250b57cec5SDimitry Andric
isPICDefaultForced() const31260b57cec5SDimitry Andric bool Generic_GCC::isPICDefaultForced() const {
31270b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
31280b57cec5SDimitry Andric }
31290b57cec5SDimitry Andric
IsIntegratedAssemblerDefault() const31300b57cec5SDimitry 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
PushPPaths(ToolChain::path_list & PPaths)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
AddMultilibPaths(const Driver & D,const std::string & SysRoot,const std::string & OSLibDir,const std::string & MultiarchTriple,path_list & Paths)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
AddMultiarchPaths(const Driver & D,const std::string & SysRoot,const std::string & OSLibDir,path_list & Paths)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
AddMultilibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const32375ffd83dbSDimitry 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
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const32560b57cec5SDimitry 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
addLibCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const3274480093f4SDimitry 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
addLibStdCXXIncludePaths(Twine IncludeDir,StringRef Triple,Twine IncludeSuffix,const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,bool DetectDebian) const3328fe6060f1SDimitry 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
addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,StringRef DebianMultiarch) const3362fe6060f1SDimitry 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
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const3423480093f4SDimitry 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 *
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef,Action::OffloadKind DeviceOffloadKind) const34320b57cec5SDimitry 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
anchor()34740b57cec5SDimitry Andric void Generic_ELF::anchor() {}
34750b57cec5SDimitry Andric
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const34760b57cec5SDimitry 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