Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
35294 views
//===--- Gnu.cpp - Gnu Tool and ToolChain Implementations -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Gnu.h"9#include "Arch/ARM.h"10#include "Arch/CSKY.h"11#include "Arch/LoongArch.h"12#include "Arch/Mips.h"13#include "Arch/PPC.h"14#include "Arch/RISCV.h"15#include "Arch/Sparc.h"16#include "Arch/SystemZ.h"17#include "CommonArgs.h"18#include "Linux.h"19#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX20#include "clang/Driver/Compilation.h"21#include "clang/Driver/Driver.h"22#include "clang/Driver/DriverDiagnostic.h"23#include "clang/Driver/MultilibBuilder.h"24#include "clang/Driver/Options.h"25#include "clang/Driver/Tool.h"26#include "clang/Driver/ToolChain.h"27#include "llvm/ADT/StringSet.h"28#include "llvm/ADT/Twine.h"29#include "llvm/Option/ArgList.h"30#include "llvm/Support/CodeGen.h"31#include "llvm/Support/Path.h"32#include "llvm/Support/VirtualFileSystem.h"33#include "llvm/TargetParser/RISCVISAInfo.h"34#include "llvm/TargetParser/TargetParser.h"35#include <system_error>3637using namespace clang::driver;38using namespace clang::driver::toolchains;39using namespace clang;40using namespace llvm::opt;4142using tools::addMultilibFlag;43using tools::addPathIfExists;4445static bool forwardToGCC(const Option &O) {46// LinkerInput options have been forwarded. Don't duplicate.47if (O.hasFlag(options::LinkerInput))48return false;49return O.matches(options::OPT_Link_Group) || O.hasFlag(options::LinkOption);50}5152// Switch CPU names not recognized by GNU assembler to a close CPU that it does53// recognize, instead of a lower march from being picked in the absence of a cpu54// flag.55static void normalizeCPUNamesForAssembler(const ArgList &Args,56ArgStringList &CmdArgs) {57if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {58StringRef CPUArg(A->getValue());59if (CPUArg.equals_insensitive("krait"))60CmdArgs.push_back("-mcpu=cortex-a15");61else if (CPUArg.equals_insensitive("kryo"))62CmdArgs.push_back("-mcpu=cortex-a57");63else64Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);65}66}6768void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,69const InputInfo &Output,70const InputInfoList &Inputs,71const ArgList &Args,72const char *LinkingOutput) const {73const Driver &D = getToolChain().getDriver();74ArgStringList CmdArgs;7576for (const auto &A : Args) {77if (forwardToGCC(A->getOption())) {78// It is unfortunate that we have to claim here, as this means79// we will basically never report anything interesting for80// platforms using a generic gcc, even if we are just using gcc81// to get to the assembler.82A->claim();8384A->render(Args, CmdArgs);85}86}8788RenderExtraToolArgs(JA, CmdArgs);8990// If using a driver, force the arch.91if (getToolChain().getTriple().isOSDarwin()) {92CmdArgs.push_back("-arch");93CmdArgs.push_back(94Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));95}9697// Try to force gcc to match the tool chain we want, if we recognize98// the arch.99//100// FIXME: The triple class should directly provide the information we want101// here.102switch (getToolChain().getArch()) {103default:104break;105case llvm::Triple::x86:106case llvm::Triple::ppc:107case llvm::Triple::ppcle:108CmdArgs.push_back("-m32");109break;110case llvm::Triple::x86_64:111case llvm::Triple::ppc64:112case llvm::Triple::ppc64le:113CmdArgs.push_back("-m64");114break;115case llvm::Triple::sparcel:116CmdArgs.push_back("-EL");117break;118}119120assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");121if (Output.isFilename()) {122CmdArgs.push_back("-o");123CmdArgs.push_back(Output.getFilename());124} else {125CmdArgs.push_back("-fsyntax-only");126}127128Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);129130// Only pass -x if gcc will understand it; otherwise hope gcc131// understands the suffix correctly. The main use case this would go132// wrong in is for linker inputs if they happened to have an odd133// suffix; really the only way to get this to happen is a command134// like '-x foobar a.c' which will treat a.c like a linker input.135//136// FIXME: For the linker case specifically, can we safely convert137// inputs into '-Wl,' options?138for (const auto &II : Inputs) {139// Don't try to pass LLVM or AST inputs to a generic gcc.140if (types::isLLVMIR(II.getType()))141D.Diag(clang::diag::err_drv_no_linker_llvm_support)142<< getToolChain().getTripleString();143else if (II.getType() == types::TY_AST)144D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString();145else if (II.getType() == types::TY_ModuleFile)146D.Diag(diag::err_drv_no_module_support)147<< getToolChain().getTripleString();148149if (types::canTypeBeUserSpecified(II.getType())) {150CmdArgs.push_back("-x");151CmdArgs.push_back(types::getTypeName(II.getType()));152}153154if (II.isFilename())155CmdArgs.push_back(II.getFilename());156else {157const Arg &A = II.getInputArg();158159// Reverse translate some rewritten options.160if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {161CmdArgs.push_back("-lstdc++");162continue;163}164165// Don't render as input, we need gcc to do the translations.166A.render(Args, CmdArgs);167}168}169170const std::string &customGCCName = D.getCCCGenericGCCName();171const char *GCCName;172if (!customGCCName.empty())173GCCName = customGCCName.c_str();174else if (D.CCCIsCXX()) {175GCCName = "g++";176} else177GCCName = "gcc";178179const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));180C.addCommand(std::make_unique<Command>(JA, *this,181ResponseFileSupport::AtFileCurCP(),182Exec, CmdArgs, Inputs, Output));183}184185void tools::gcc::Preprocessor::RenderExtraToolArgs(186const JobAction &JA, ArgStringList &CmdArgs) const {187CmdArgs.push_back("-E");188}189190void tools::gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,191ArgStringList &CmdArgs) const {192const Driver &D = getToolChain().getDriver();193194switch (JA.getType()) {195// If -flto, etc. are present then make sure not to force assembly output.196case types::TY_LLVM_IR:197case types::TY_LTO_IR:198case types::TY_LLVM_BC:199case types::TY_LTO_BC:200CmdArgs.push_back("-c");201break;202// We assume we've got an "integrated" assembler in that gcc will produce an203// object file itself.204case types::TY_Object:205CmdArgs.push_back("-c");206break;207case types::TY_PP_Asm:208CmdArgs.push_back("-S");209break;210case types::TY_Nothing:211CmdArgs.push_back("-fsyntax-only");212break;213default:214D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());215}216}217218void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,219ArgStringList &CmdArgs) const {220// The types are (hopefully) good enough.221}222223static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {224switch (T.getArch()) {225case llvm::Triple::x86:226if (T.isOSIAMCU())227return "elf_iamcu";228return "elf_i386";229case llvm::Triple::aarch64:230return "aarch64linux";231case llvm::Triple::aarch64_be:232return "aarch64linuxb";233case llvm::Triple::arm:234case llvm::Triple::thumb:235case llvm::Triple::armeb:236case llvm::Triple::thumbeb:237return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi"238: "armelf_linux_eabi";239case llvm::Triple::m68k:240return "m68kelf";241case llvm::Triple::ppc:242if (T.isOSLinux())243return "elf32ppclinux";244return "elf32ppc";245case llvm::Triple::ppcle:246if (T.isOSLinux())247return "elf32lppclinux";248return "elf32lppc";249case llvm::Triple::ppc64:250return "elf64ppc";251case llvm::Triple::ppc64le:252return "elf64lppc";253case llvm::Triple::riscv32:254return "elf32lriscv";255case llvm::Triple::riscv64:256return "elf64lriscv";257case llvm::Triple::sparc:258case llvm::Triple::sparcel:259return "elf32_sparc";260case llvm::Triple::sparcv9:261return "elf64_sparc";262case llvm::Triple::loongarch32:263return "elf32loongarch";264case llvm::Triple::loongarch64:265return "elf64loongarch";266case llvm::Triple::mips:267return "elf32btsmip";268case llvm::Triple::mipsel:269return "elf32ltsmip";270case llvm::Triple::mips64:271if (tools::mips::hasMipsAbiArg(Args, "n32") ||272T.getEnvironment() == llvm::Triple::GNUABIN32)273return "elf32btsmipn32";274return "elf64btsmip";275case llvm::Triple::mips64el:276if (tools::mips::hasMipsAbiArg(Args, "n32") ||277T.getEnvironment() == llvm::Triple::GNUABIN32)278return "elf32ltsmipn32";279return "elf64ltsmip";280case llvm::Triple::systemz:281return "elf64_s390";282case llvm::Triple::x86_64:283if (T.isX32())284return "elf32_x86_64";285return "elf_x86_64";286case llvm::Triple::ve:287return "elf64ve";288case llvm::Triple::csky:289return "cskyelf_linux";290default:291return nullptr;292}293}294295static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {296bool HasStaticPIE = Args.hasArg(options::OPT_static_pie);297if (HasStaticPIE && Args.hasArg(options::OPT_no_pie)) {298const Driver &D = TC.getDriver();299const llvm::opt::OptTable &Opts = D.getOpts();300StringRef StaticPIEName = Opts.getOptionName(options::OPT_static_pie);301StringRef NoPIEName = Opts.getOptionName(options::OPT_nopie);302D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;303}304return HasStaticPIE;305}306307static bool getStatic(const ArgList &Args) {308return Args.hasArg(options::OPT_static) &&309!Args.hasArg(options::OPT_static_pie);310}311312void tools::gnutools::StaticLibTool::ConstructJob(313Compilation &C, const JobAction &JA, const InputInfo &Output,314const InputInfoList &Inputs, const ArgList &Args,315const char *LinkingOutput) const {316const Driver &D = getToolChain().getDriver();317318// Silence warning for "clang -g foo.o -o foo"319Args.ClaimAllArgs(options::OPT_g_Group);320// and "clang -emit-llvm foo.o -o foo"321Args.ClaimAllArgs(options::OPT_emit_llvm);322// and for "clang -w foo.o -o foo". Other warning options are already323// handled somewhere else.324Args.ClaimAllArgs(options::OPT_w);325// Silence warnings when linking C code with a C++ '-stdlib' argument.326Args.ClaimAllArgs(options::OPT_stdlib_EQ);327328// ar tool command "llvm-ar <options> <output_file> <input_files>".329ArgStringList CmdArgs;330// Create and insert file members with a deterministic index.331CmdArgs.push_back("rcsD");332CmdArgs.push_back(Output.getFilename());333334for (const auto &II : Inputs) {335if (II.isFilename()) {336CmdArgs.push_back(II.getFilename());337}338}339340// Delete old output archive file if it already exists before generating a new341// archive file.342auto OutputFileName = Output.getFilename();343if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {344if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {345D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();346return;347}348}349350const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());351C.addCommand(std::make_unique<Command>(JA, *this,352ResponseFileSupport::AtFileCurCP(),353Exec, CmdArgs, Inputs, Output));354}355356void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,357const InputInfo &Output,358const InputInfoList &Inputs,359const ArgList &Args,360const char *LinkingOutput) const {361// FIXME: The Linker class constructor takes a ToolChain and not a362// Generic_ELF, so the static_cast might return a reference to a invalid363// instance (see PR45061). Ideally, the Linker constructor needs to take a364// Generic_ELF instead.365const auto &ToolChain = static_cast<const Generic_ELF &>(getToolChain());366const Driver &D = ToolChain.getDriver();367368const llvm::Triple &Triple = getToolChain().getEffectiveTriple();369370const llvm::Triple::ArchType Arch = ToolChain.getArch();371const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily();372const bool isAndroid = ToolChain.getTriple().isAndroid();373const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();374const bool IsVE = ToolChain.getTriple().isVE();375const bool IsStaticPIE = getStaticPIE(Args, ToolChain);376const bool IsStatic = getStatic(Args);377const bool HasCRTBeginEndFiles =378ToolChain.getTriple().hasEnvironment() ||379(ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);380381ArgStringList CmdArgs;382383// Silence warning for "clang -g foo.o -o foo"384Args.ClaimAllArgs(options::OPT_g_Group);385// and "clang -emit-llvm foo.o -o foo"386Args.ClaimAllArgs(options::OPT_emit_llvm);387// and for "clang -w foo.o -o foo". Other warning options are already388// handled somewhere else.389Args.ClaimAllArgs(options::OPT_w);390391if (!D.SysRoot.empty())392CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));393394if (Args.hasArg(options::OPT_s))395CmdArgs.push_back("-s");396397if (Triple.isARM() || Triple.isThumb()) {398bool IsBigEndian = arm::isARMBigEndian(Triple, Args);399if (IsBigEndian)400arm::appendBE8LinkFlag(Args, CmdArgs, Triple);401CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");402} else if (Triple.isAArch64()) {403CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");404}405406// Most Android ARM64 targets should enable the linker fix for erratum407// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.408if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) {409std::string CPU = getCPUName(D, Args, Triple);410if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")411CmdArgs.push_back("--fix-cortex-a53-843419");412}413414ToolChain.addExtraOpts(CmdArgs);415416CmdArgs.push_back("--eh-frame-hdr");417418if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {419CmdArgs.push_back("-m");420CmdArgs.push_back(LDMOption);421} else {422D.Diag(diag::err_target_unknown_triple) << Triple.str();423return;424}425426if (Triple.isRISCV()) {427CmdArgs.push_back("-X");428if (Args.hasArg(options::OPT_mno_relax))429CmdArgs.push_back("--no-relax");430}431432const bool IsShared = Args.hasArg(options::OPT_shared);433if (IsShared)434CmdArgs.push_back("-shared");435bool IsPIE = false;436if (IsStaticPIE) {437CmdArgs.push_back("-static");438CmdArgs.push_back("-pie");439CmdArgs.push_back("--no-dynamic-linker");440CmdArgs.push_back("-z");441CmdArgs.push_back("text");442} else if (IsStatic) {443CmdArgs.push_back("-static");444} else if (!Args.hasArg(options::OPT_r)) {445if (Args.hasArg(options::OPT_rdynamic))446CmdArgs.push_back("-export-dynamic");447if (!IsShared) {448IsPIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie,449ToolChain.isPIEDefault(Args));450if (IsPIE)451CmdArgs.push_back("-pie");452CmdArgs.push_back("-dynamic-linker");453CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +454ToolChain.getDynamicLinker(Args)));455}456}457458CmdArgs.push_back("-o");459CmdArgs.push_back(Output.getFilename());460461if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,462options::OPT_r)) {463if (!isAndroid && !IsIAMCU) {464const char *crt1 = nullptr;465if (!Args.hasArg(options::OPT_shared)) {466if (Args.hasArg(options::OPT_pg))467crt1 = "gcrt1.o";468else if (IsPIE)469crt1 = "Scrt1.o";470else if (IsStaticPIE)471crt1 = "rcrt1.o";472else473crt1 = "crt1.o";474}475if (crt1)476CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));477478CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));479}480481if (IsVE) {482CmdArgs.push_back("-z");483CmdArgs.push_back("max-page-size=0x4000000");484}485486if (IsIAMCU)487CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));488else if (HasCRTBeginEndFiles) {489std::string P;490if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&491!isAndroid) {492std::string crtbegin = ToolChain.getCompilerRT(Args, "crtbegin",493ToolChain::FT_Object);494if (ToolChain.getVFS().exists(crtbegin))495P = crtbegin;496}497if (P.empty()) {498const char *crtbegin;499if (Args.hasArg(options::OPT_shared))500crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";501else if (IsStatic)502crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";503else if (IsPIE || IsStaticPIE)504crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";505else506crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";507P = ToolChain.GetFilePath(crtbegin);508}509CmdArgs.push_back(Args.MakeArgString(P));510}511512// Add crtfastmath.o if available and fast math is enabled.513ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);514515if (isAndroid && Args.hasFlag(options::OPT_fandroid_pad_segment,516options::OPT_fno_android_pad_segment, false))517CmdArgs.push_back(518Args.MakeArgString(ToolChain.GetFilePath("crt_pad_segment.o")));519}520521Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});522523ToolChain.AddFilePathLibArgs(Args, CmdArgs);524525if (D.isUsingLTO()) {526assert(!Inputs.empty() && "Must have at least one input.");527// Find the first filename InputInfo object.528auto Input = llvm::find_if(529Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });530if (Input == Inputs.end())531// For a very rare case, all of the inputs to the linker are532// InputArg. If that happens, just use the first InputInfo.533Input = Inputs.begin();534535addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,536D.getLTOMode() == LTOK_Thin);537}538539if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))540CmdArgs.push_back("--no-demangle");541542bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);543bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);544addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);545AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);546547addHIPRuntimeLibArgs(ToolChain, C, Args, CmdArgs);548549// The profile runtime also needs access to system libraries.550getToolChain().addProfileRTLibs(Args, CmdArgs);551552if (D.CCCIsCXX() &&553!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,554options::OPT_r)) {555if (ToolChain.ShouldLinkCXXStdlib(Args)) {556bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&557!Args.hasArg(options::OPT_static);558if (OnlyLibstdcxxStatic)559CmdArgs.push_back("-Bstatic");560ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);561if (OnlyLibstdcxxStatic)562CmdArgs.push_back("-Bdynamic");563}564CmdArgs.push_back("-lm");565}566567// Silence warnings when linking C code with a C++ '-stdlib' argument.568Args.ClaimAllArgs(options::OPT_stdlib_EQ);569570// Additional linker set-up and flags for Fortran. This is required in order571// to generate executables. As Fortran runtime depends on the C runtime,572// these dependencies need to be listed before the C runtime below (i.e.573// AddRunTimeLibs).574if (D.IsFlangMode()) {575addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);576addFortranRuntimeLibs(ToolChain, Args, CmdArgs);577CmdArgs.push_back("-lm");578}579580if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {581if (!Args.hasArg(options::OPT_nodefaultlibs)) {582if (IsStatic || IsStaticPIE)583CmdArgs.push_back("--start-group");584585if (NeedsSanitizerDeps)586linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);587588if (NeedsXRayDeps)589linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);590591bool WantPthread = Args.hasArg(options::OPT_pthread) ||592Args.hasArg(options::OPT_pthreads);593594// Use the static OpenMP runtime with -static-openmp595bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&596!Args.hasArg(options::OPT_static);597598// FIXME: Only pass GompNeedsRT = true for platforms with libgomp that599// require librt. Most modern Linux platforms do, but some may not.600if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP,601JA.isHostOffloading(Action::OFK_OpenMP),602/* GompNeedsRT= */ true))603// OpenMP runtimes implies pthreads when using the GNU toolchain.604// FIXME: Does this really make sense for all GNU toolchains?605WantPthread = true;606607AddRunTimeLibs(ToolChain, D, CmdArgs, Args);608609// LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so610// forcibly link with libatomic as a workaround.611// TODO: Issue #41880 and D118021.612if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {613CmdArgs.push_back("--push-state");614CmdArgs.push_back("--as-needed");615CmdArgs.push_back("-latomic");616CmdArgs.push_back("--pop-state");617}618619// We don't need libpthread neither for bionic (Android) nor for musl,620// (used by OHOS as runtime library).621if (WantPthread && !isAndroid && !isOHOSFamily)622CmdArgs.push_back("-lpthread");623624if (Args.hasArg(options::OPT_fsplit_stack))625CmdArgs.push_back("--wrap=pthread_create");626627if (!Args.hasArg(options::OPT_nolibc))628CmdArgs.push_back("-lc");629630// Add IAMCU specific libs, if needed.631if (IsIAMCU)632CmdArgs.push_back("-lgloss");633634if (IsStatic || IsStaticPIE)635CmdArgs.push_back("--end-group");636else637AddRunTimeLibs(ToolChain, D, CmdArgs, Args);638639// Add IAMCU specific libs (outside the group), if needed.640if (IsIAMCU) {641CmdArgs.push_back("--as-needed");642CmdArgs.push_back("-lsoftfp");643CmdArgs.push_back("--no-as-needed");644}645}646647if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) {648if (HasCRTBeginEndFiles) {649std::string P;650if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT &&651!isAndroid) {652std::string crtend = ToolChain.getCompilerRT(Args, "crtend",653ToolChain::FT_Object);654if (ToolChain.getVFS().exists(crtend))655P = crtend;656}657if (P.empty()) {658const char *crtend;659if (Args.hasArg(options::OPT_shared))660crtend = isAndroid ? "crtend_so.o" : "crtendS.o";661else if (IsPIE || IsStaticPIE)662crtend = isAndroid ? "crtend_android.o" : "crtendS.o";663else664crtend = isAndroid ? "crtend_android.o" : "crtend.o";665P = ToolChain.GetFilePath(crtend);666}667CmdArgs.push_back(Args.MakeArgString(P));668}669if (!isAndroid)670CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));671}672}673674Args.AddAllArgs(CmdArgs, options::OPT_T);675676const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());677C.addCommand(std::make_unique<Command>(JA, *this,678ResponseFileSupport::AtFileCurCP(),679Exec, CmdArgs, Inputs, Output));680}681682void tools::gnutools::Assembler::ConstructJob(Compilation &C,683const JobAction &JA,684const InputInfo &Output,685const InputInfoList &Inputs,686const ArgList &Args,687const char *LinkingOutput) const {688const auto &D = getToolChain().getDriver();689690claimNoWarnArgs(Args);691692ArgStringList CmdArgs;693694llvm::Reloc::Model RelocationModel;695unsigned PICLevel;696bool IsPIE;697const char *DefaultAssembler = "as";698// Enforce GNU as on Solaris; the native assembler's input syntax isn't fully699// compatible.700if (getToolChain().getTriple().isOSSolaris())701DefaultAssembler = "gas";702std::tie(RelocationModel, PICLevel, IsPIE) =703ParsePICArgs(getToolChain(), Args);704705if (const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ)) {706if (A->getOption().getID() == options::OPT_gz) {707CmdArgs.push_back("--compress-debug-sections");708} else {709StringRef Value = A->getValue();710if (Value == "none" || Value == "zlib" || Value == "zstd") {711CmdArgs.push_back(712Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));713} else {714D.Diag(diag::err_drv_unsupported_option_argument)715<< A->getSpelling() << Value;716}717}718}719720switch (getToolChain().getArch()) {721default:722break;723// Add --32/--64 to make sure we get the format we want.724// This is incomplete725case llvm::Triple::x86:726CmdArgs.push_back("--32");727break;728case llvm::Triple::x86_64:729if (getToolChain().getTriple().isX32())730CmdArgs.push_back("--x32");731else732CmdArgs.push_back("--64");733break;734case llvm::Triple::ppc: {735CmdArgs.push_back("-a32");736CmdArgs.push_back("-mppc");737CmdArgs.push_back("-mbig-endian");738CmdArgs.push_back(ppc::getPPCAsmModeForCPU(739getCPUName(D, Args, getToolChain().getTriple())));740break;741}742case llvm::Triple::ppcle: {743CmdArgs.push_back("-a32");744CmdArgs.push_back("-mppc");745CmdArgs.push_back("-mlittle-endian");746CmdArgs.push_back(ppc::getPPCAsmModeForCPU(747getCPUName(D, Args, getToolChain().getTriple())));748break;749}750case llvm::Triple::ppc64: {751CmdArgs.push_back("-a64");752CmdArgs.push_back("-mppc64");753CmdArgs.push_back("-mbig-endian");754CmdArgs.push_back(ppc::getPPCAsmModeForCPU(755getCPUName(D, Args, getToolChain().getTriple())));756break;757}758case llvm::Triple::ppc64le: {759CmdArgs.push_back("-a64");760CmdArgs.push_back("-mppc64");761CmdArgs.push_back("-mlittle-endian");762CmdArgs.push_back(ppc::getPPCAsmModeForCPU(763getCPUName(D, Args, getToolChain().getTriple())));764break;765}766case llvm::Triple::riscv32:767case llvm::Triple::riscv64: {768StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());769CmdArgs.push_back("-mabi");770CmdArgs.push_back(ABIName.data());771std::string MArchName =772riscv::getRISCVArch(Args, getToolChain().getTriple());773CmdArgs.push_back("-march");774CmdArgs.push_back(Args.MakeArgString(MArchName));775if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))776Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);777break;778}779case llvm::Triple::sparc:780case llvm::Triple::sparcel: {781CmdArgs.push_back("-32");782std::string CPU = getCPUName(D, Args, getToolChain().getTriple());783CmdArgs.push_back(784sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));785AddAssemblerKPIC(getToolChain(), Args, CmdArgs);786break;787}788case llvm::Triple::sparcv9: {789CmdArgs.push_back("-64");790std::string CPU = getCPUName(D, Args, getToolChain().getTriple());791CmdArgs.push_back(792sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));793AddAssemblerKPIC(getToolChain(), Args, CmdArgs);794break;795}796case llvm::Triple::arm:797case llvm::Triple::armeb:798case llvm::Triple::thumb:799case llvm::Triple::thumbeb: {800const llvm::Triple &Triple2 = getToolChain().getTriple();801CmdArgs.push_back(arm::isARMBigEndian(Triple2, Args) ? "-EB" : "-EL");802switch (Triple2.getSubArch()) {803case llvm::Triple::ARMSubArch_v7:804CmdArgs.push_back("-mfpu=neon");805break;806case llvm::Triple::ARMSubArch_v8:807CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");808break;809default:810break;811}812813switch (arm::getARMFloatABI(getToolChain(), Args)) {814case arm::FloatABI::Invalid: llvm_unreachable("must have an ABI!");815case arm::FloatABI::Soft:816CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=soft"));817break;818case arm::FloatABI::SoftFP:819CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=softfp"));820break;821case arm::FloatABI::Hard:822CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=hard"));823break;824}825826Args.AddLastArg(CmdArgs, options::OPT_march_EQ);827normalizeCPUNamesForAssembler(Args, CmdArgs);828829Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);830// The integrated assembler doesn't implement e_flags setting behavior for831// -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For832// compatibility we accept but warn.833if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))834A->ignoreTargetSpecific();835break;836}837case llvm::Triple::aarch64:838case llvm::Triple::aarch64_be: {839CmdArgs.push_back(840getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL");841Args.AddLastArg(CmdArgs, options::OPT_march_EQ);842normalizeCPUNamesForAssembler(Args, CmdArgs);843844break;845}846// TODO: handle loongarch32.847case llvm::Triple::loongarch64: {848StringRef ABIName =849loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());850CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));851break;852}853case llvm::Triple::mips:854case llvm::Triple::mipsel:855case llvm::Triple::mips64:856case llvm::Triple::mips64el: {857StringRef CPUName;858StringRef ABIName;859mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);860ABIName = mips::getGnuCompatibleMipsABIName(ABIName);861862CmdArgs.push_back("-march");863CmdArgs.push_back(CPUName.data());864865CmdArgs.push_back("-mabi");866CmdArgs.push_back(ABIName.data());867868// -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,869// or -mshared (not implemented) is in effect.870if (RelocationModel == llvm::Reloc::Static)871CmdArgs.push_back("-mno-shared");872873// LLVM doesn't support -mplt yet and acts as if it is always given.874// However, -mplt has no effect with the N64 ABI.875if (ABIName != "64" && !Args.hasArg(options::OPT_mno_abicalls))876CmdArgs.push_back("-call_nonpic");877878if (getToolChain().getTriple().isLittleEndian())879CmdArgs.push_back("-EL");880else881CmdArgs.push_back("-EB");882883if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {884if (StringRef(A->getValue()) == "2008")885CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));886}887888// Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.889if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,890options::OPT_mfp64)) {891A->claim();892A->render(Args, CmdArgs);893} else if (mips::shouldUseFPXX(894Args, getToolChain().getTriple(), CPUName, ABIName,895mips::getMipsFloatABI(getToolChain().getDriver(), Args,896getToolChain().getTriple())))897CmdArgs.push_back("-mfpxx");898899// Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of900// -mno-mips16 is actually -no-mips16.901if (Arg *A =902Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16)) {903if (A->getOption().matches(options::OPT_mips16)) {904A->claim();905A->render(Args, CmdArgs);906} else {907A->claim();908CmdArgs.push_back("-no-mips16");909}910}911912Args.AddLastArg(CmdArgs, options::OPT_mmicromips,913options::OPT_mno_micromips);914Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);915Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);916917if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {918// Do not use AddLastArg because not all versions of MIPS assembler919// support -mmsa / -mno-msa options.920if (A->getOption().matches(options::OPT_mmsa))921CmdArgs.push_back(Args.MakeArgString("-mmsa"));922}923924Args.AddLastArg(CmdArgs, options::OPT_mhard_float,925options::OPT_msoft_float);926927Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,928options::OPT_msingle_float);929930Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,931options::OPT_mno_odd_spreg);932933AddAssemblerKPIC(getToolChain(), Args, CmdArgs);934break;935}936case llvm::Triple::systemz: {937// Always pass an -march option, since our default of z10 is later938// than the GNU assembler's default.939std::string CPUName = systemz::getSystemZTargetCPU(Args);940CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));941break;942}943case llvm::Triple::ve:944DefaultAssembler = "nas";945}946947for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,948options::OPT_fdebug_prefix_map_EQ)) {949StringRef Map = A->getValue();950if (!Map.contains('='))951D.Diag(diag::err_drv_invalid_argument_to_option)952<< Map << A->getOption().getName();953else {954CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));955CmdArgs.push_back(Args.MakeArgString(Map));956}957A->claim();958}959960Args.AddAllArgs(CmdArgs, options::OPT_I);961Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);962963CmdArgs.push_back("-o");964CmdArgs.push_back(Output.getFilename());965966for (const auto &II : Inputs)967CmdArgs.push_back(II.getFilename());968969if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group,970options::OPT_gdwarf_2, options::OPT_gdwarf_3,971options::OPT_gdwarf_4, options::OPT_gdwarf_5,972options::OPT_gdwarf))973if (!A->getOption().matches(options::OPT_g0)) {974Args.AddLastArg(CmdArgs, options::OPT_g_Flag);975976unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);977CmdArgs.push_back(Args.MakeArgString("-gdwarf-" + Twine(DwarfVersion)));978}979980const char *Exec =981Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));982C.addCommand(std::make_unique<Command>(JA, *this,983ResponseFileSupport::AtFileCurCP(),984Exec, CmdArgs, Inputs, Output));985986// Handle the debug info splitting at object creation time if we're987// creating an object.988// TODO: Currently only works on linux with newer objcopy.989if (Args.hasArg(options::OPT_gsplit_dwarf) &&990getToolChain().getTriple().isOSLinux())991SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,992SplitDebugName(JA, Args, Inputs[0], Output));993}994995namespace {996// Filter to remove Multilibs that don't exist as a suffix to Path997class FilterNonExistent {998StringRef Base, File;999llvm::vfs::FileSystem &VFS;10001001public:1002FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)1003: Base(Base), File(File), VFS(VFS) {}1004bool operator()(const Multilib &M) {1005return !VFS.exists(Base + M.gccSuffix() + File);1006}1007};1008} // end anonymous namespace10091010static bool isSoftFloatABI(const ArgList &Args) {1011Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,1012options::OPT_mfloat_abi_EQ);1013if (!A)1014return false;10151016return A->getOption().matches(options::OPT_msoft_float) ||1017(A->getOption().matches(options::OPT_mfloat_abi_EQ) &&1018A->getValue() == StringRef("soft"));1019}10201021static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {1022return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;1023}10241025static bool isMipsEL(llvm::Triple::ArchType Arch) {1026return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;1027}10281029static bool isMips16(const ArgList &Args) {1030Arg *A = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);1031return A && A->getOption().matches(options::OPT_mips16);1032}10331034static bool isMicroMips(const ArgList &Args) {1035Arg *A = Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);1036return A && A->getOption().matches(options::OPT_mmicromips);1037}10381039static bool isMSP430(llvm::Triple::ArchType Arch) {1040return Arch == llvm::Triple::msp430;1041}10421043static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,1044FilterNonExistent &NonExistent,1045DetectedMultilibs &Result) {1046// Check for Code Sourcery toolchain multilibs1047MultilibSet CSMipsMultilibs;1048{1049auto MArchMips16 = MultilibBuilder("/mips16").flag("-m32").flag("-mips16");10501051auto MArchMicroMips =1052MultilibBuilder("/micromips").flag("-m32").flag("-mmicromips");10531054auto MArchDefault = MultilibBuilder("")1055.flag("-mips16", /*Disallow=*/true)1056.flag("-mmicromips", /*Disallow=*/true);10571058auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");10591060auto SoftFloat = MultilibBuilder("/soft-float").flag("-msoft-float");10611062auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");10631064auto DefaultFloat = MultilibBuilder("")1065.flag("-msoft-float", /*Disallow=*/true)1066.flag("-mnan=2008", /*Disallow=*/true);10671068auto BigEndian =1069MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);10701071auto LittleEndian =1072MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);10731074// Note that this one's osSuffix is ""1075auto MAbi64 = MultilibBuilder("")1076.gccSuffix("/64")1077.includeSuffix("/64")1078.flag("-mabi=n64")1079.flag("-mabi=n32", /*Disallow=*/true)1080.flag("-m32", /*Disallow=*/true);10811082CSMipsMultilibs =1083MultilibSetBuilder()1084.Either(MArchMips16, MArchMicroMips, MArchDefault)1085.Maybe(UCLibc)1086.Either(SoftFloat, Nan2008, DefaultFloat)1087.FilterOut("/micromips/nan2008")1088.FilterOut("/mips16/nan2008")1089.Either(BigEndian, LittleEndian)1090.Maybe(MAbi64)1091.FilterOut("/mips16.*/64")1092.FilterOut("/micromips.*/64")1093.makeMultilibSet()1094.FilterOut(NonExistent)1095.setIncludeDirsCallback([](const Multilib &M) {1096std::vector<std::string> Dirs({"/include"});1097if (StringRef(M.includeSuffix()).starts_with("/uclibc"))1098Dirs.push_back(1099"/../../../../mips-linux-gnu/libc/uclibc/usr/include");1100else1101Dirs.push_back("/../../../../mips-linux-gnu/libc/usr/include");1102return Dirs;1103});1104}11051106MultilibSet DebianMipsMultilibs;1107{1108MultilibBuilder MAbiN32 =1109MultilibBuilder().gccSuffix("/n32").includeSuffix("/n32").flag(1110"-mabi=n32");11111112MultilibBuilder M64 = MultilibBuilder()1113.gccSuffix("/64")1114.includeSuffix("/64")1115.flag("-m64")1116.flag("-m32", /*Disallow=*/true)1117.flag("-mabi=n32", /*Disallow=*/true);11181119MultilibBuilder M32 = MultilibBuilder()1120.gccSuffix("/32")1121.flag("-m64", /*Disallow=*/true)1122.flag("-m32")1123.flag("-mabi=n32", /*Disallow=*/true);11241125DebianMipsMultilibs = MultilibSetBuilder()1126.Either(M32, M64, MAbiN32)1127.makeMultilibSet()1128.FilterOut(NonExistent);1129}11301131// Sort candidates. Toolchain that best meets the directories tree goes first.1132// Then select the first toolchains matches command line flags.1133MultilibSet *Candidates[] = {&CSMipsMultilibs, &DebianMipsMultilibs};1134if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())1135std::iter_swap(Candidates, Candidates + 1);1136for (const MultilibSet *Candidate : Candidates) {1137if (Candidate->select(Flags, Result.SelectedMultilibs)) {1138if (Candidate == &DebianMipsMultilibs)1139Result.BiarchSibling = Multilib();1140Result.Multilibs = *Candidate;1141return true;1142}1143}1144return false;1145}11461147static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,1148const Multilib::flags_list &Flags,1149FilterNonExistent &NonExistent,1150DetectedMultilibs &Result) {11511152MultilibSet AndroidMipsMultilibs =1153MultilibSetBuilder()1154.Maybe(MultilibBuilder("/mips-r2", {}, {}).flag("-march=mips32r2"))1155.Maybe(MultilibBuilder("/mips-r6", {}, {}).flag("-march=mips32r6"))1156.makeMultilibSet()1157.FilterOut(NonExistent);11581159MultilibSet AndroidMipselMultilibs =1160MultilibSetBuilder()1161.Either(MultilibBuilder().flag("-march=mips32"),1162MultilibBuilder("/mips-r2", "", "/mips-r2")1163.flag("-march=mips32r2"),1164MultilibBuilder("/mips-r6", "", "/mips-r6")1165.flag("-march=mips32r6"))1166.makeMultilibSet()1167.FilterOut(NonExistent);11681169MultilibSet AndroidMips64elMultilibs =1170MultilibSetBuilder()1171.Either(MultilibBuilder().flag("-march=mips64r6"),1172MultilibBuilder("/32/mips-r1", "", "/mips-r1")1173.flag("-march=mips32"),1174MultilibBuilder("/32/mips-r2", "", "/mips-r2")1175.flag("-march=mips32r2"),1176MultilibBuilder("/32/mips-r6", "", "/mips-r6")1177.flag("-march=mips32r6"))1178.makeMultilibSet()1179.FilterOut(NonExistent);11801181MultilibSet *MS = &AndroidMipsMultilibs;1182if (VFS.exists(Path + "/mips-r6"))1183MS = &AndroidMipselMultilibs;1184else if (VFS.exists(Path + "/32"))1185MS = &AndroidMips64elMultilibs;1186if (MS->select(Flags, Result.SelectedMultilibs)) {1187Result.Multilibs = *MS;1188return true;1189}1190return false;1191}11921193static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,1194FilterNonExistent &NonExistent,1195DetectedMultilibs &Result) {1196// Musl toolchain multilibs1197MultilibSet MuslMipsMultilibs;1198{1199auto MArchMipsR2 = MultilibBuilder("")1200.osSuffix("/mips-r2-hard-musl")1201.flag("-EB")1202.flag("-EL", /*Disallow=*/true)1203.flag("-march=mips32r2");12041205auto MArchMipselR2 = MultilibBuilder("/mipsel-r2-hard-musl")1206.flag("-EB", /*Disallow=*/true)1207.flag("-EL")1208.flag("-march=mips32r2");12091210MuslMipsMultilibs = MultilibSetBuilder()1211.Either(MArchMipsR2, MArchMipselR2)1212.makeMultilibSet();12131214// Specify the callback that computes the include directories.1215MuslMipsMultilibs.setIncludeDirsCallback([](const Multilib &M) {1216return std::vector<std::string>(1217{"/../sysroot" + M.osSuffix() + "/usr/include"});1218});1219}1220if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs)) {1221Result.Multilibs = MuslMipsMultilibs;1222return true;1223}1224return false;1225}12261227static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,1228FilterNonExistent &NonExistent,1229DetectedMultilibs &Result) {1230// CodeScape MTI toolchain v1.2 and early.1231MultilibSet MtiMipsMultilibsV1;1232{1233auto MArchMips32 = MultilibBuilder("/mips32")1234.flag("-m32")1235.flag("-m64", /*Disallow=*/true)1236.flag("-mmicromips", /*Disallow=*/true)1237.flag("-march=mips32");12381239auto MArchMicroMips = MultilibBuilder("/micromips")1240.flag("-m32")1241.flag("-m64", /*Disallow=*/true)1242.flag("-mmicromips");12431244auto MArchMips64r2 = MultilibBuilder("/mips64r2")1245.flag("-m32", /*Disallow=*/true)1246.flag("-m64")1247.flag("-march=mips64r2");12481249auto MArchMips64 = MultilibBuilder("/mips64")1250.flag("-m32", /*Disallow=*/true)1251.flag("-m64")1252.flag("-march=mips64r2", /*Disallow=*/true);12531254auto MArchDefault = MultilibBuilder("")1255.flag("-m32")1256.flag("-m64", /*Disallow=*/true)1257.flag("-mmicromips", /*Disallow=*/true)1258.flag("-march=mips32r2");12591260auto Mips16 = MultilibBuilder("/mips16").flag("-mips16");12611262auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");12631264auto MAbi64 = MultilibBuilder("/64")1265.flag("-mabi=n64")1266.flag("-mabi=n32", /*Disallow=*/true)1267.flag("-m32", /*Disallow=*/true);12681269auto BigEndian =1270MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);12711272auto LittleEndian =1273MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);12741275auto SoftFloat = MultilibBuilder("/sof").flag("-msoft-float");12761277auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");12781279MtiMipsMultilibsV1 =1280MultilibSetBuilder()1281.Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64,1282MArchDefault)1283.Maybe(UCLibc)1284.Maybe(Mips16)1285.FilterOut("/mips64/mips16")1286.FilterOut("/mips64r2/mips16")1287.FilterOut("/micromips/mips16")1288.Maybe(MAbi64)1289.FilterOut("/micromips/64")1290.FilterOut("/mips32/64")1291.FilterOut("^/64")1292.FilterOut("/mips16/64")1293.Either(BigEndian, LittleEndian)1294.Maybe(SoftFloat)1295.Maybe(Nan2008)1296.FilterOut(".*sof/nan2008")1297.makeMultilibSet()1298.FilterOut(NonExistent)1299.setIncludeDirsCallback([](const Multilib &M) {1300std::vector<std::string> Dirs({"/include"});1301if (StringRef(M.includeSuffix()).starts_with("/uclibc"))1302Dirs.push_back("/../../../../sysroot/uclibc/usr/include");1303else1304Dirs.push_back("/../../../../sysroot/usr/include");1305return Dirs;1306});1307}13081309// CodeScape IMG toolchain starting from v1.3.1310MultilibSet MtiMipsMultilibsV2;1311{1312auto BeHard = MultilibBuilder("/mips-r2-hard")1313.flag("-EB")1314.flag("-msoft-float", /*Disallow=*/true)1315.flag("-mnan=2008", /*Disallow=*/true)1316.flag("-muclibc", /*Disallow=*/true);1317auto BeSoft = MultilibBuilder("/mips-r2-soft")1318.flag("-EB")1319.flag("-msoft-float")1320.flag("-mnan=2008", /*Disallow=*/true);1321auto ElHard = MultilibBuilder("/mipsel-r2-hard")1322.flag("-EL")1323.flag("-msoft-float", /*Disallow=*/true)1324.flag("-mnan=2008", /*Disallow=*/true)1325.flag("-muclibc", /*Disallow=*/true);1326auto ElSoft = MultilibBuilder("/mipsel-r2-soft")1327.flag("-EL")1328.flag("-msoft-float")1329.flag("-mnan=2008", /*Disallow=*/true)1330.flag("-mmicromips", /*Disallow=*/true);1331auto BeHardNan = MultilibBuilder("/mips-r2-hard-nan2008")1332.flag("-EB")1333.flag("-msoft-float", /*Disallow=*/true)1334.flag("-mnan=2008")1335.flag("-muclibc", /*Disallow=*/true);1336auto ElHardNan = MultilibBuilder("/mipsel-r2-hard-nan2008")1337.flag("-EL")1338.flag("-msoft-float", /*Disallow=*/true)1339.flag("-mnan=2008")1340.flag("-muclibc", /*Disallow=*/true)1341.flag("-mmicromips", /*Disallow=*/true);1342auto BeHardNanUclibc = MultilibBuilder("/mips-r2-hard-nan2008-uclibc")1343.flag("-EB")1344.flag("-msoft-float", /*Disallow=*/true)1345.flag("-mnan=2008")1346.flag("-muclibc");1347auto ElHardNanUclibc = MultilibBuilder("/mipsel-r2-hard-nan2008-uclibc")1348.flag("-EL")1349.flag("-msoft-float", /*Disallow=*/true)1350.flag("-mnan=2008")1351.flag("-muclibc");1352auto BeHardUclibc = MultilibBuilder("/mips-r2-hard-uclibc")1353.flag("-EB")1354.flag("-msoft-float", /*Disallow=*/true)1355.flag("-mnan=2008", /*Disallow=*/true)1356.flag("-muclibc");1357auto ElHardUclibc = MultilibBuilder("/mipsel-r2-hard-uclibc")1358.flag("-EL")1359.flag("-msoft-float", /*Disallow=*/true)1360.flag("-mnan=2008", /*Disallow=*/true)1361.flag("-muclibc");1362auto ElMicroHardNan = MultilibBuilder("/micromipsel-r2-hard-nan2008")1363.flag("-EL")1364.flag("-msoft-float", /*Disallow=*/true)1365.flag("-mnan=2008")1366.flag("-mmicromips");1367auto ElMicroSoft = MultilibBuilder("/micromipsel-r2-soft")1368.flag("-EL")1369.flag("-msoft-float")1370.flag("-mnan=2008", /*Disallow=*/true)1371.flag("-mmicromips");13721373auto O32 = MultilibBuilder("/lib")1374.osSuffix("")1375.flag("-mabi=n32", /*Disallow=*/true)1376.flag("-mabi=n64", /*Disallow=*/true);1377auto N32 = MultilibBuilder("/lib32")1378.osSuffix("")1379.flag("-mabi=n32")1380.flag("-mabi=n64", /*Disallow=*/true);1381auto N64 = MultilibBuilder("/lib64")1382.osSuffix("")1383.flag("-mabi=n32", /*Disallow=*/true)1384.flag("-mabi=n64");13851386MtiMipsMultilibsV2 =1387MultilibSetBuilder()1388.Either({BeHard, BeSoft, ElHard, ElSoft, BeHardNan, ElHardNan,1389BeHardNanUclibc, ElHardNanUclibc, BeHardUclibc,1390ElHardUclibc, ElMicroHardNan, ElMicroSoft})1391.Either(O32, N32, N64)1392.makeMultilibSet()1393.FilterOut(NonExistent)1394.setIncludeDirsCallback([](const Multilib &M) {1395return std::vector<std::string>({"/../../../../sysroot" +1396M.includeSuffix() +1397"/../usr/include"});1398})1399.setFilePathsCallback([](const Multilib &M) {1400return std::vector<std::string>(1401{"/../../../../mips-mti-linux-gnu/lib" + M.gccSuffix()});1402});1403}1404for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {1405if (Candidate->select(Flags, Result.SelectedMultilibs)) {1406Result.Multilibs = *Candidate;1407return true;1408}1409}1410return false;1411}14121413static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,1414FilterNonExistent &NonExistent,1415DetectedMultilibs &Result) {1416// CodeScape IMG toolchain v1.2 and early.1417MultilibSet ImgMultilibsV1;1418{1419auto Mips64r6 = MultilibBuilder("/mips64r6")1420.flag("-m64")1421.flag("-m32", /*Disallow=*/true);14221423auto LittleEndian =1424MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);14251426auto MAbi64 = MultilibBuilder("/64")1427.flag("-mabi=n64")1428.flag("-mabi=n32", /*Disallow=*/true)1429.flag("-m32", /*Disallow=*/true);14301431ImgMultilibsV1 =1432MultilibSetBuilder()1433.Maybe(Mips64r6)1434.Maybe(MAbi64)1435.Maybe(LittleEndian)1436.makeMultilibSet()1437.FilterOut(NonExistent)1438.setIncludeDirsCallback([](const Multilib &M) {1439return std::vector<std::string>(1440{"/include", "/../../../../sysroot/usr/include"});1441});1442}14431444// CodeScape IMG toolchain starting from v1.3.1445MultilibSet ImgMultilibsV2;1446{1447auto BeHard = MultilibBuilder("/mips-r6-hard")1448.flag("-EB")1449.flag("-msoft-float", /*Disallow=*/true)1450.flag("-mmicromips", /*Disallow=*/true);1451auto BeSoft = MultilibBuilder("/mips-r6-soft")1452.flag("-EB")1453.flag("-msoft-float")1454.flag("-mmicromips", /*Disallow=*/true);1455auto ElHard = MultilibBuilder("/mipsel-r6-hard")1456.flag("-EL")1457.flag("-msoft-float", /*Disallow=*/true)1458.flag("-mmicromips", /*Disallow=*/true);1459auto ElSoft = MultilibBuilder("/mipsel-r6-soft")1460.flag("-EL")1461.flag("-msoft-float")1462.flag("-mmicromips", /*Disallow=*/true);1463auto BeMicroHard = MultilibBuilder("/micromips-r6-hard")1464.flag("-EB")1465.flag("-msoft-float", /*Disallow=*/true)1466.flag("-mmicromips");1467auto BeMicroSoft = MultilibBuilder("/micromips-r6-soft")1468.flag("-EB")1469.flag("-msoft-float")1470.flag("-mmicromips");1471auto ElMicroHard = MultilibBuilder("/micromipsel-r6-hard")1472.flag("-EL")1473.flag("-msoft-float", /*Disallow=*/true)1474.flag("-mmicromips");1475auto ElMicroSoft = MultilibBuilder("/micromipsel-r6-soft")1476.flag("-EL")1477.flag("-msoft-float")1478.flag("-mmicromips");14791480auto O32 = MultilibBuilder("/lib")1481.osSuffix("")1482.flag("-mabi=n32", /*Disallow=*/true)1483.flag("-mabi=n64", /*Disallow=*/true);1484auto N32 = MultilibBuilder("/lib32")1485.osSuffix("")1486.flag("-mabi=n32")1487.flag("-mabi=n64", /*Disallow=*/true);1488auto N64 = MultilibBuilder("/lib64")1489.osSuffix("")1490.flag("-mabi=n32", /*Disallow=*/true)1491.flag("-mabi=n64");14921493ImgMultilibsV2 =1494MultilibSetBuilder()1495.Either({BeHard, BeSoft, ElHard, ElSoft, BeMicroHard, BeMicroSoft,1496ElMicroHard, ElMicroSoft})1497.Either(O32, N32, N64)1498.makeMultilibSet()1499.FilterOut(NonExistent)1500.setIncludeDirsCallback([](const Multilib &M) {1501return std::vector<std::string>({"/../../../../sysroot" +1502M.includeSuffix() +1503"/../usr/include"});1504})1505.setFilePathsCallback([](const Multilib &M) {1506return std::vector<std::string>(1507{"/../../../../mips-img-linux-gnu/lib" + M.gccSuffix()});1508});1509}1510for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {1511if (Candidate->select(Flags, Result.SelectedMultilibs)) {1512Result.Multilibs = *Candidate;1513return true;1514}1515}1516return false;1517}15181519bool clang::driver::findMIPSMultilibs(const Driver &D,1520const llvm::Triple &TargetTriple,1521StringRef Path, const ArgList &Args,1522DetectedMultilibs &Result) {1523FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());15241525StringRef CPUName;1526StringRef ABIName;1527tools::mips::getMipsCPUAndABI(Args, TargetTriple, CPUName, ABIName);15281529llvm::Triple::ArchType TargetArch = TargetTriple.getArch();15301531Multilib::flags_list Flags;1532addMultilibFlag(TargetTriple.isMIPS32(), "-m32", Flags);1533addMultilibFlag(TargetTriple.isMIPS64(), "-m64", Flags);1534addMultilibFlag(isMips16(Args), "-mips16", Flags);1535addMultilibFlag(CPUName == "mips32", "-march=mips32", Flags);1536addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||1537CPUName == "mips32r5" || CPUName == "p5600",1538"-march=mips32r2", Flags);1539addMultilibFlag(CPUName == "mips32r6", "-march=mips32r6", Flags);1540addMultilibFlag(CPUName == "mips64", "-march=mips64", Flags);1541addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||1542CPUName == "mips64r5" || CPUName == "octeon" ||1543CPUName == "octeon+",1544"-march=mips64r2", Flags);1545addMultilibFlag(CPUName == "mips64r6", "-march=mips64r6", Flags);1546addMultilibFlag(isMicroMips(Args), "-mmicromips", Flags);1547addMultilibFlag(tools::mips::isUCLibc(Args), "-muclibc", Flags);1548addMultilibFlag(tools::mips::isNaN2008(D, Args, TargetTriple), "-mnan=2008",1549Flags);1550addMultilibFlag(ABIName == "n32", "-mabi=n32", Flags);1551addMultilibFlag(ABIName == "n64", "-mabi=n64", Flags);1552addMultilibFlag(isSoftFloatABI(Args), "-msoft-float", Flags);1553addMultilibFlag(!isSoftFloatABI(Args), "-mhard-float", Flags);1554addMultilibFlag(isMipsEL(TargetArch), "-EL", Flags);1555addMultilibFlag(!isMipsEL(TargetArch), "-EB", Flags);15561557if (TargetTriple.isAndroid())1558return findMipsAndroidMultilibs(D.getVFS(), Path, Flags, NonExistent,1559Result);15601561if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&1562TargetTriple.getOS() == llvm::Triple::Linux &&1563TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)1564return findMipsMuslMultilibs(Flags, NonExistent, Result);15651566if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&1567TargetTriple.getOS() == llvm::Triple::Linux &&1568TargetTriple.isGNUEnvironment())1569return findMipsMtiMultilibs(Flags, NonExistent, Result);15701571if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&1572TargetTriple.getOS() == llvm::Triple::Linux &&1573TargetTriple.isGNUEnvironment())1574return findMipsImgMultilibs(Flags, NonExistent, Result);15751576if (findMipsCsMultilibs(Flags, NonExistent, Result))1577return true;15781579// Fallback to the regular toolchain-tree structure.1580Multilib Default;1581Result.Multilibs.push_back(Default);1582Result.Multilibs.FilterOut(NonExistent);15831584if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) {1585Result.BiarchSibling = Multilib();1586return true;1587}15881589return false;1590}15911592static void findAndroidArmMultilibs(const Driver &D,1593const llvm::Triple &TargetTriple,1594StringRef Path, const ArgList &Args,1595DetectedMultilibs &Result) {1596// Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb.1597FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());1598MultilibBuilder ArmV7Multilib = MultilibBuilder("/armv7-a")1599.flag("-march=armv7-a")1600.flag("-mthumb", /*Disallow=*/true);1601MultilibBuilder ThumbMultilib = MultilibBuilder("/thumb")1602.flag("-march=armv7-a", /*Disallow=*/true)1603.flag("-mthumb");1604MultilibBuilder ArmV7ThumbMultilib =1605MultilibBuilder("/armv7-a/thumb").flag("-march=armv7-a").flag("-mthumb");1606MultilibBuilder DefaultMultilib =1607MultilibBuilder("")1608.flag("-march=armv7-a", /*Disallow=*/true)1609.flag("-mthumb", /*Disallow=*/true);1610MultilibSet AndroidArmMultilibs =1611MultilibSetBuilder()1612.Either(ThumbMultilib, ArmV7Multilib, ArmV7ThumbMultilib,1613DefaultMultilib)1614.makeMultilibSet()1615.FilterOut(NonExistent);16161617Multilib::flags_list Flags;1618llvm::StringRef Arch = Args.getLastArgValue(options::OPT_march_EQ);1619bool IsArmArch = TargetTriple.getArch() == llvm::Triple::arm;1620bool IsThumbArch = TargetTriple.getArch() == llvm::Triple::thumb;1621bool IsV7SubArch = TargetTriple.getSubArch() == llvm::Triple::ARMSubArch_v7;1622bool IsThumbMode = IsThumbArch ||1623Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, false) ||1624(IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::ISAKind::THUMB);1625bool IsArmV7Mode = (IsArmArch || IsThumbArch) &&1626(llvm::ARM::parseArchVersion(Arch) == 7 ||1627(IsArmArch && Arch == "" && IsV7SubArch));1628addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);1629addMultilibFlag(IsThumbMode, "-mthumb", Flags);16301631if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs))1632Result.Multilibs = AndroidArmMultilibs;1633}16341635static bool findMSP430Multilibs(const Driver &D,1636const llvm::Triple &TargetTriple,1637StringRef Path, const ArgList &Args,1638DetectedMultilibs &Result) {1639FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());1640MultilibBuilder WithoutExceptions =1641MultilibBuilder("/430").flag("-exceptions", /*Disallow=*/true);1642MultilibBuilder WithExceptions =1643MultilibBuilder("/430/exceptions").flag("-exceptions");16441645// FIXME: when clang starts to support msp430x ISA additional logic1646// to select between multilib must be implemented1647// MultilibBuilder MSP430xMultilib = MultilibBuilder("/large");16481649Result.Multilibs.push_back(WithoutExceptions.makeMultilib());1650Result.Multilibs.push_back(WithExceptions.makeMultilib());1651Result.Multilibs.FilterOut(NonExistent);16521653Multilib::flags_list Flags;1654addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,1655options::OPT_fno_exceptions, false),1656"-exceptions", Flags);1657if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))1658return true;16591660return false;1661}16621663static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,1664StringRef Path, const ArgList &Args,1665DetectedMultilibs &Result) {1666FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());16671668tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);1669std::optional<llvm::StringRef> Res =1670tools::csky::getCSKYArchName(D, Args, TargetTriple);16711672if (!Res)1673return;1674auto ARCHName = *Res;16751676Multilib::flags_list Flags;1677addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "-hard-fp",1678Flags);1679addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "-soft-fp",1680Flags);1681addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "-soft", Flags);1682addMultilibFlag(ARCHName == "ck801", "-march=ck801", Flags);1683addMultilibFlag(ARCHName == "ck802", "-march=ck802", Flags);1684addMultilibFlag(ARCHName == "ck803", "-march=ck803", Flags);1685addMultilibFlag(ARCHName == "ck804", "-march=ck804", Flags);1686addMultilibFlag(ARCHName == "ck805", "-march=ck805", Flags);1687addMultilibFlag(ARCHName == "ck807", "-march=ck807", Flags);1688addMultilibFlag(ARCHName == "ck810", "-march=ck810", Flags);1689addMultilibFlag(ARCHName == "ck810v", "-march=ck810v", Flags);1690addMultilibFlag(ARCHName == "ck860", "-march=ck860", Flags);1691addMultilibFlag(ARCHName == "ck860v", "-march=ck860v", Flags);16921693bool isBigEndian = false;1694if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,1695options::OPT_mbig_endian))1696isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);1697addMultilibFlag(isBigEndian, "-EB", Flags);16981699auto HardFloat = MultilibBuilder("/hard-fp").flag("-hard-fp");1700auto SoftFpFloat = MultilibBuilder("/soft-fp").flag("-soft-fp");1701auto SoftFloat = MultilibBuilder("").flag("-soft");1702auto Arch801 = MultilibBuilder("/ck801").flag("-march=ck801");1703auto Arch802 = MultilibBuilder("/ck802").flag("-march=ck802");1704auto Arch803 = MultilibBuilder("/ck803").flag("-march=ck803");1705// CK804 use the same library as CK8031706auto Arch804 = MultilibBuilder("/ck803").flag("-march=ck804");1707auto Arch805 = MultilibBuilder("/ck805").flag("-march=ck805");1708auto Arch807 = MultilibBuilder("/ck807").flag("-march=ck807");1709auto Arch810 = MultilibBuilder("").flag("-march=ck810");1710auto Arch810v = MultilibBuilder("/ck810v").flag("-march=ck810v");1711auto Arch860 = MultilibBuilder("/ck860").flag("-march=ck860");1712auto Arch860v = MultilibBuilder("/ck860v").flag("-march=ck860v");1713auto BigEndian = MultilibBuilder("/big").flag("-EB");17141715MultilibSet CSKYMultilibs =1716MultilibSetBuilder()1717.Maybe(BigEndian)1718.Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,1719Arch810, Arch810v, Arch860, Arch860v})1720.Either(HardFloat, SoftFpFloat, SoftFloat)1721.makeMultilibSet()1722.FilterOut(NonExistent);17231724if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs))1725Result.Multilibs = CSKYMultilibs;1726}17271728/// Extend the multi-lib re-use selection mechanism for RISC-V.1729/// This function will try to re-use multi-lib if they are compatible.1730/// Definition of compatible:1731/// - ABI must be the same.1732/// - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im1733/// is a subset of march=rv32imc.1734/// - march that contains atomic extension can't reuse multi-lib that1735/// doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and1736/// march=rv32ima are not compatible, because software and hardware1737/// atomic operation can't work together correctly.1738static bool1739selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch,1740const Multilib::flags_list &Flags,1741llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {1742// Try to find the perfect matching multi-lib first.1743if (RISCVMultilibSet.select(Flags, SelectedMultilibs))1744return true;17451746Multilib::flags_list NewFlags;1747std::vector<MultilibBuilder> NewMultilibs;17481749llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult =1750llvm::RISCVISAInfo::parseArchString(1751Arch, /*EnableExperimentalExtension=*/true,1752/*ExperimentalExtensionVersionCheck=*/false);1753// Ignore any error here, we assume it will be handled in another place.1754if (llvm::errorToBool(ParseResult.takeError()))1755return false;17561757auto &ISAInfo = *ParseResult;17581759addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags);1760addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags);17611762// Collect all flags except march=*1763for (StringRef Flag : Flags) {1764if (Flag.starts_with("!march=") || Flag.starts_with("-march="))1765continue;17661767NewFlags.push_back(Flag.str());1768}17691770llvm::StringSet<> AllArchExts;1771// Reconstruct multi-lib list, and break march option into separated1772// extension. e.g. march=rv32im -> +i +m1773for (const auto &M : RISCVMultilibSet) {1774bool Skip = false;17751776MultilibBuilder NewMultilib =1777MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix());1778for (StringRef Flag : M.flags()) {1779// Add back all flags except -march.1780if (!Flag.consume_front("-march=")) {1781NewMultilib.flag(Flag);1782continue;1783}17841785// Break down -march into individual extension.1786llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult =1787llvm::RISCVISAInfo::parseArchString(1788Flag, /*EnableExperimentalExtension=*/true,1789/*ExperimentalExtensionVersionCheck=*/false);1790// Ignore any error here, we assume it will handled in another place.1791if (llvm::errorToBool(MLConfigParseResult.takeError())) {1792// We might get a parsing error if rv32e in the list, we could just skip1793// that and process the rest of multi-lib configs.1794Skip = true;1795continue;1796}1797auto &MLConfigISAInfo = *MLConfigParseResult;17981799for (auto &MLConfigArchExt : MLConfigISAInfo->getExtensions()) {1800auto ExtName = MLConfigArchExt.first;1801NewMultilib.flag(Twine("-", ExtName).str());18021803if (AllArchExts.insert(ExtName).second) {1804addMultilibFlag(ISAInfo->hasExtension(ExtName),1805Twine("-", ExtName).str(), NewFlags);1806}1807}18081809// Check the XLEN explicitly.1810if (MLConfigISAInfo->getXLen() == 32) {1811NewMultilib.flag("-m32");1812NewMultilib.flag("-m64", /*Disallow*/ true);1813} else {1814NewMultilib.flag("-m32", /*Disallow*/ true);1815NewMultilib.flag("-m64");1816}18171818// Atomic extension must be explicitly checked, soft and hard atomic1819// operation never co-work correctly.1820if (!MLConfigISAInfo->hasExtension("a"))1821NewMultilib.flag("-a", /*Disallow*/ true);1822}18231824if (Skip)1825continue;18261827NewMultilibs.emplace_back(NewMultilib);1828}18291830// Build an internal used only multi-lib list, used for checking any1831// compatible multi-lib.1832MultilibSet NewRISCVMultilibs =1833MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();18341835if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs))1836for (const Multilib &NewSelectedM : SelectedMultilibs)1837for (const auto &M : RISCVMultilibSet)1838// Look up the corresponding multi-lib entry in original multi-lib set.1839if (M.gccSuffix() == NewSelectedM.gccSuffix())1840return true;18411842return false;1843}18441845static void findRISCVBareMetalMultilibs(const Driver &D,1846const llvm::Triple &TargetTriple,1847StringRef Path, const ArgList &Args,1848DetectedMultilibs &Result) {1849FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());1850struct RiscvMultilib {1851StringRef march;1852StringRef mabi;1853};1854// currently only support the set of multilibs like riscv-gnu-toolchain does.1855// TODO: support MULTILIB_REUSE1856constexpr RiscvMultilib RISCVMultilibSet[] = {1857{"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"},1858{"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},1859{"rv64imafdc", "lp64d"}};18601861std::vector<MultilibBuilder> Ms;1862for (auto Element : RISCVMultilibSet) {1863// multilib path rule is ${march}/${mabi}1864Ms.emplace_back(1865MultilibBuilder(1866(Twine(Element.march) + "/" + Twine(Element.mabi)).str())1867.flag(Twine("-march=", Element.march).str())1868.flag(Twine("-mabi=", Element.mabi).str()));1869}1870MultilibSet RISCVMultilibs =1871MultilibSetBuilder()1872.Either(Ms)1873.makeMultilibSet()1874.FilterOut(NonExistent)1875.setFilePathsCallback([](const Multilib &M) {1876return std::vector<std::string>(1877{M.gccSuffix(),1878"/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),1879"/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});1880});18811882Multilib::flags_list Flags;1883llvm::StringSet<> Added_ABIs;1884StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);1885std::string MArch = tools::riscv::getRISCVArch(Args, TargetTriple);1886for (auto Element : RISCVMultilibSet) {1887addMultilibFlag(MArch == Element.march,1888Twine("-march=", Element.march).str().c_str(), Flags);1889if (!Added_ABIs.count(Element.mabi)) {1890Added_ABIs.insert(Element.mabi);1891addMultilibFlag(ABIName == Element.mabi,1892Twine("-mabi=", Element.mabi).str().c_str(), Flags);1893}1894}18951896if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags,1897Result.SelectedMultilibs))1898Result.Multilibs = RISCVMultilibs;1899}19001901static void findRISCVMultilibs(const Driver &D,1902const llvm::Triple &TargetTriple, StringRef Path,1903const ArgList &Args, DetectedMultilibs &Result) {1904if (TargetTriple.getOS() == llvm::Triple::UnknownOS)1905return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);19061907FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());1908MultilibBuilder Ilp32 =1909MultilibBuilder("lib32/ilp32").flag("-m32").flag("-mabi=ilp32");1910MultilibBuilder Ilp32f =1911MultilibBuilder("lib32/ilp32f").flag("-m32").flag("-mabi=ilp32f");1912MultilibBuilder Ilp32d =1913MultilibBuilder("lib32/ilp32d").flag("-m32").flag("-mabi=ilp32d");1914MultilibBuilder Lp64 =1915MultilibBuilder("lib64/lp64").flag("-m64").flag("-mabi=lp64");1916MultilibBuilder Lp64f =1917MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");1918MultilibBuilder Lp64d =1919MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");1920MultilibSet RISCVMultilibs =1921MultilibSetBuilder()1922.Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})1923.makeMultilibSet()1924.FilterOut(NonExistent);19251926Multilib::flags_list Flags;1927bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;1928StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);19291930addMultilibFlag(!IsRV64, "-m32", Flags);1931addMultilibFlag(IsRV64, "-m64", Flags);1932addMultilibFlag(ABIName == "ilp32", "-mabi=ilp32", Flags);1933addMultilibFlag(ABIName == "ilp32f", "-mabi=ilp32f", Flags);1934addMultilibFlag(ABIName == "ilp32d", "-mabi=ilp32d", Flags);1935addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);1936addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);1937addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);19381939if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs))1940Result.Multilibs = RISCVMultilibs;1941}19421943static bool findBiarchMultilibs(const Driver &D,1944const llvm::Triple &TargetTriple,1945StringRef Path, const ArgList &Args,1946bool NeedsBiarchSuffix,1947DetectedMultilibs &Result) {1948MultilibBuilder DefaultBuilder;19491950// Some versions of SUSE and Fedora on ppc64 put 32-bit libs1951// in what would normally be GCCInstallPath and put the 64-bit1952// libs in a subdirectory named 64. The simple logic we follow is that1953// *if* there is a subdirectory of the right name with crtbegin.o in it,1954// we use that. If not, and if not a biarch triple alias, we look for1955// crtbegin.o without the subdirectory.19561957StringRef Suff64 = "/64";1958// Solaris uses platform-specific suffixes instead of /64.1959if (TargetTriple.isOSSolaris()) {1960switch (TargetTriple.getArch()) {1961case llvm::Triple::x86:1962case llvm::Triple::x86_64:1963Suff64 = "/amd64";1964break;1965case llvm::Triple::sparc:1966case llvm::Triple::sparcv9:1967Suff64 = "/sparcv9";1968break;1969default:1970break;1971}1972}19731974Multilib Alt64 = MultilibBuilder()1975.gccSuffix(Suff64)1976.includeSuffix(Suff64)1977.flag("-m32", /*Disallow=*/true)1978.flag("-m64")1979.flag("-mx32", /*Disallow=*/true)1980.makeMultilib();1981Multilib Alt32 = MultilibBuilder()1982.gccSuffix("/32")1983.includeSuffix("/32")1984.flag("-m32")1985.flag("-m64", /*Disallow=*/true)1986.flag("-mx32", /*Disallow=*/true)1987.makeMultilib();1988Multilib Altx32 = MultilibBuilder()1989.gccSuffix("/x32")1990.includeSuffix("/x32")1991.flag("-m32", /*Disallow=*/true)1992.flag("-m64", /*Disallow=*/true)1993.flag("-mx32")1994.makeMultilib();1995Multilib Alt32sparc = MultilibBuilder()1996.gccSuffix("/sparcv8plus")1997.includeSuffix("/sparcv8plus")1998.flag("-m32")1999.flag("-m64", /*Disallow=*/true)2000.makeMultilib();20012002// GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.2003FilterNonExistent NonExistent(2004Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", D.getVFS());20052006// Determine default multilib from: 32, 64, x322007// Also handle cases such as 64 on 32, 32 on 64, etc.2008enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;2009const bool IsX32 = TargetTriple.isX32();2010if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))2011Want = WANT64;2012if (TargetTriple.isArch32Bit() && !NonExistent(Alt32sparc))2013Want = WANT64;2014else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))2015Want = WANT64;2016else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64))2017Want = WANT32;2018else if (TargetTriple.isArch64Bit() && !NonExistent(Alt32sparc))2019Want = WANT64;2020else {2021if (TargetTriple.isArch32Bit())2022Want = NeedsBiarchSuffix ? WANT64 : WANT32;2023else if (IsX32)2024Want = NeedsBiarchSuffix ? WANT64 : WANTX32;2025else2026Want = NeedsBiarchSuffix ? WANT32 : WANT64;2027}20282029if (Want == WANT32)2030DefaultBuilder.flag("-m32")2031.flag("-m64", /*Disallow=*/true)2032.flag("-mx32", /*Disallow=*/true);2033else if (Want == WANT64)2034DefaultBuilder.flag("-m32", /*Disallow=*/true)2035.flag("-m64")2036.flag("-mx32", /*Disallow=*/true);2037else if (Want == WANTX32)2038DefaultBuilder.flag("-m32", /*Disallow=*/true)2039.flag("-m64", /*Disallow=*/true)2040.flag("-mx32");2041else2042return false;20432044Multilib Default = DefaultBuilder.makeMultilib();20452046Result.Multilibs.push_back(Default);2047Result.Multilibs.push_back(Alt64);2048Result.Multilibs.push_back(Alt32);2049Result.Multilibs.push_back(Altx32);2050Result.Multilibs.push_back(Alt32sparc);20512052Result.Multilibs.FilterOut(NonExistent);20532054Multilib::flags_list Flags;2055addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "-m64", Flags);2056addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);2057addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);20582059if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs))2060return false;20612062if (Result.SelectedMultilibs.back() == Alt64 ||2063Result.SelectedMultilibs.back() == Alt32 ||2064Result.SelectedMultilibs.back() == Altx32 ||2065Result.SelectedMultilibs.back() == Alt32sparc)2066Result.BiarchSibling = Default;20672068return true;2069}20702071/// Generic_GCC - A tool chain using the 'gcc' command to perform2072/// all subcommands; this relies on gcc translating the majority of2073/// command line options.20742075/// Less-than for GCCVersion, implementing a Strict Weak Ordering.2076bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,2077int RHSPatch,2078StringRef RHSPatchSuffix) const {2079if (Major != RHSMajor)2080return Major < RHSMajor;2081if (Minor != RHSMinor) {2082// Note that versions without a specified minor sort higher than those with2083// a minor.2084if (RHSMinor == -1)2085return true;2086if (Minor == -1)2087return false;2088return Minor < RHSMinor;2089}2090if (Patch != RHSPatch) {2091// Note that versions without a specified patch sort higher than those with2092// a patch.2093if (RHSPatch == -1)2094return true;2095if (Patch == -1)2096return false;20972098// Otherwise just sort on the patch itself.2099return Patch < RHSPatch;2100}2101if (PatchSuffix != RHSPatchSuffix) {2102// Sort empty suffixes higher.2103if (RHSPatchSuffix.empty())2104return true;2105if (PatchSuffix.empty())2106return false;21072108// Provide a lexicographic sort to make this a total ordering.2109return PatchSuffix < RHSPatchSuffix;2110}21112112// The versions are equal.2113return false;2114}21152116/// Parse a GCCVersion object out of a string of text.2117///2118/// This is the primary means of forming GCCVersion objects.2119/*static*/2120Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {2121const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""};2122std::pair<StringRef, StringRef> First = VersionText.split('.');2123std::pair<StringRef, StringRef> Second = First.second.split('.');21242125StringRef MajorStr = First.first;2126StringRef MinorStr = Second.first;2127StringRef PatchStr = Second.second;21282129GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};21302131// Parse version number strings such as:2132// 52133// 4.42134// 4.4-patched2135// 4.4.02136// 4.4.x2137// 4.4.2-rc42138// 4.4.x-patched2139// 10-win322140// Split on '.', handle 1, 2 or 3 such segments. Each segment must contain2141// purely a number, except for the last one, where a non-number suffix2142// is stored in PatchSuffix. The third segment is allowed to not contain2143// a number at all.21442145auto TryParseLastNumber = [&](StringRef Segment, int &Number,2146std::string &OutStr) -> bool {2147// Look for a number prefix and parse that, and split out any trailing2148// string into GoodVersion.PatchSuffix.21492150if (size_t EndNumber = Segment.find_first_not_of("0123456789")) {2151StringRef NumberStr = Segment.slice(0, EndNumber);2152if (NumberStr.getAsInteger(10, Number) || Number < 0)2153return false;2154OutStr = NumberStr;2155GoodVersion.PatchSuffix = Segment.substr(EndNumber);2156return true;2157}2158return false;2159};2160auto TryParseNumber = [](StringRef Segment, int &Number) -> bool {2161if (Segment.getAsInteger(10, Number) || Number < 0)2162return false;2163return true;2164};21652166if (MinorStr.empty()) {2167// If no minor string, major is the last segment2168if (!TryParseLastNumber(MajorStr, GoodVersion.Major, GoodVersion.MajorStr))2169return BadVersion;2170return GoodVersion;2171}21722173if (!TryParseNumber(MajorStr, GoodVersion.Major))2174return BadVersion;2175GoodVersion.MajorStr = MajorStr;21762177if (PatchStr.empty()) {2178// If no patch string, minor is the last segment2179if (!TryParseLastNumber(MinorStr, GoodVersion.Minor, GoodVersion.MinorStr))2180return BadVersion;2181return GoodVersion;2182}21832184if (!TryParseNumber(MinorStr, GoodVersion.Minor))2185return BadVersion;2186GoodVersion.MinorStr = MinorStr;21872188// For the last segment, tolerate a missing number.2189std::string DummyStr;2190TryParseLastNumber(PatchStr, GoodVersion.Patch, DummyStr);2191return GoodVersion;2192}21932194static llvm::StringRef getGCCToolchainDir(const ArgList &Args,2195llvm::StringRef SysRoot) {2196const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);2197if (A)2198return A->getValue();21992200// If we have a SysRoot, ignore GCC_INSTALL_PREFIX.2201// GCC_INSTALL_PREFIX specifies the gcc installation for the default2202// sysroot and is likely not valid with a different sysroot.2203if (!SysRoot.empty())2204return "";22052206return GCC_INSTALL_PREFIX;2207}22082209/// Initialize a GCCInstallationDetector from the driver.2210///2211/// This performs all of the autodetection and sets up the various paths.2212/// Once constructed, a GCCInstallationDetector is essentially immutable.2213///2214/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and2215/// should instead pull the target out of the driver. This is currently2216/// necessary because the driver doesn't store the final version of the target2217/// triple.2218void Generic_GCC::GCCInstallationDetector::init(2219const llvm::Triple &TargetTriple, const ArgList &Args) {2220llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()2221? TargetTriple.get64BitArchVariant()2222: TargetTriple.get32BitArchVariant();2223// The library directories which may contain GCC installations.2224SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;2225// The compatible GCC triples for this particular architecture.2226SmallVector<StringRef, 16> CandidateTripleAliases;2227SmallVector<StringRef, 16> CandidateBiarchTripleAliases;2228// Add some triples that we want to check first.2229CandidateTripleAliases.push_back(TargetTriple.str());2230std::string TripleNoVendor, BiarchTripleNoVendor;2231if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) {2232StringRef OSEnv = TargetTriple.getOSAndEnvironmentName();2233if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32)2234OSEnv = "linux-gnu";2235TripleNoVendor = (TargetTriple.getArchName().str() + '-' + OSEnv).str();2236CandidateTripleAliases.push_back(TripleNoVendor);2237if (BiarchVariantTriple.getArch() != llvm::Triple::UnknownArch) {2238BiarchTripleNoVendor =2239(BiarchVariantTriple.getArchName().str() + '-' + OSEnv).str();2240CandidateBiarchTripleAliases.push_back(BiarchTripleNoVendor);2241}2242}22432244CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,2245CandidateTripleAliases, CandidateBiarchLibDirs,2246CandidateBiarchTripleAliases);22472248// If --gcc-install-dir= is specified, skip filesystem detection.2249if (const Arg *A =2250Args.getLastArg(clang::driver::options::OPT_gcc_install_dir_EQ);2251A && A->getValue()[0]) {2252StringRef InstallDir = A->getValue();2253if (!ScanGCCForMultilibs(TargetTriple, Args, InstallDir, false)) {2254D.Diag(diag::err_drv_invalid_gcc_install_dir) << InstallDir;2255} else {2256(void)InstallDir.consume_back("/");2257StringRef VersionText = llvm::sys::path::filename(InstallDir);2258StringRef TripleText =2259llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));22602261Version = GCCVersion::Parse(VersionText);2262GCCTriple.setTriple(TripleText);2263GCCInstallPath = std::string(InstallDir);2264GCCParentLibPath = GCCInstallPath + "/../../..";2265IsValid = true;2266}2267return;2268}22692270// If --gcc-triple is specified use this instead of trying to2271// auto-detect a triple.2272if (const Arg *A =2273Args.getLastArg(clang::driver::options::OPT_gcc_triple_EQ)) {2274StringRef GCCTriple = A->getValue();2275CandidateTripleAliases.clear();2276CandidateTripleAliases.push_back(GCCTriple);2277}22782279// Compute the set of prefixes for our search.2280SmallVector<std::string, 8> Prefixes;2281StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);2282if (GCCToolchainDir != "") {2283if (GCCToolchainDir.back() == '/')2284GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /22852286Prefixes.push_back(std::string(GCCToolchainDir));2287} else {2288// If we have a SysRoot, try that first.2289if (!D.SysRoot.empty()) {2290Prefixes.push_back(D.SysRoot);2291AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);2292}22932294// Then look for gcc installed alongside clang.2295Prefixes.push_back(D.Dir + "/..");22962297// Next, look for prefix(es) that correspond to distribution-supplied gcc2298// installations.2299if (D.SysRoot.empty()) {2300// Typically /usr.2301AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);2302}23032304// Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.2305// This avoids accidentally enforcing the system GCC version when using a2306// custom toolchain.2307SmallVector<StringRef, 16> GentooTestTriples;2308// Try to match an exact triple as target triple first.2309// e.g. crossdev -S x86_64-gentoo-linux-gnu will install gcc libs for2310// x86_64-gentoo-linux-gnu. But "clang -target x86_64-gentoo-linux-gnu"2311// may pick the libraries for x86_64-pc-linux-gnu even when exact matching2312// triple x86_64-gentoo-linux-gnu is present.2313GentooTestTriples.push_back(TargetTriple.str());2314GentooTestTriples.append(CandidateTripleAliases.begin(),2315CandidateTripleAliases.end());2316if (ScanGentooConfigs(TargetTriple, Args, GentooTestTriples,2317CandidateBiarchTripleAliases))2318return;2319}23202321// Loop over the various components which exist and select the best GCC2322// installation available. GCC installs are ranked by version number.2323const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");2324Version = VersionZero;2325for (const std::string &Prefix : Prefixes) {2326auto &VFS = D.getVFS();2327if (!VFS.exists(Prefix))2328continue;2329for (StringRef Suffix : CandidateLibDirs) {2330const std::string LibDir = concat(Prefix, Suffix);2331if (!VFS.exists(LibDir))2332continue;2333// Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.2334bool GCCDirExists = VFS.exists(LibDir + "/gcc");2335bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");2336for (StringRef Candidate : CandidateTripleAliases)2337ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,2338GCCDirExists, GCCCrossDirExists);2339}2340for (StringRef Suffix : CandidateBiarchLibDirs) {2341const std::string LibDir = Prefix + Suffix.str();2342if (!VFS.exists(LibDir))2343continue;2344bool GCCDirExists = VFS.exists(LibDir + "/gcc");2345bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");2346for (StringRef Candidate : CandidateBiarchTripleAliases)2347ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,2348GCCDirExists, GCCCrossDirExists);2349}23502351// Skip other prefixes once a GCC installation is found.2352if (Version > VersionZero)2353break;2354}2355}23562357void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {2358for (const auto &InstallPath : CandidateGCCInstallPaths)2359OS << "Found candidate GCC installation: " << InstallPath << "\n";23602361if (!GCCInstallPath.empty())2362OS << "Selected GCC installation: " << GCCInstallPath << "\n";23632364for (const auto &Multilib : Multilibs)2365OS << "Candidate multilib: " << Multilib << "\n";23662367if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())2368OS << "Selected multilib: " << SelectedMultilib << "\n";2369}23702371bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {2372if (BiarchSibling) {2373M = *BiarchSibling;2374return true;2375}2376return false;2377}23782379void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(2380const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes,2381StringRef SysRoot) {23822383if (TargetTriple.isOSHaiku()) {2384Prefixes.push_back(concat(SysRoot, "/boot/system/develop/tools"));2385return;2386}23872388if (TargetTriple.isOSSolaris()) {2389// Solaris is a special case.2390// The GCC installation is under2391// /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/2392// so we need to find those /usr/gcc/*/lib/gcc libdirs and go with2393// /usr/gcc/<version> as a prefix.23942395SmallVector<std::pair<GCCVersion, std::string>, 8> SolarisPrefixes;2396std::string PrefixDir = concat(SysRoot, "/usr/gcc");2397std::error_code EC;2398for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),2399LE;2400!EC && LI != LE; LI = LI.increment(EC)) {2401StringRef VersionText = llvm::sys::path::filename(LI->path());2402GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);24032404// Filter out obviously bad entries.2405if (CandidateVersion.Major == -1 || CandidateVersion.isOlderThan(4, 1, 1))2406continue;24072408std::string CandidatePrefix = PrefixDir + "/" + VersionText.str();2409std::string CandidateLibPath = CandidatePrefix + "/lib/gcc";2410if (!D.getVFS().exists(CandidateLibPath))2411continue;24122413SolarisPrefixes.emplace_back(2414std::make_pair(CandidateVersion, CandidatePrefix));2415}2416// Sort in reverse order so GCCInstallationDetector::init picks the latest.2417std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend());2418for (auto p : SolarisPrefixes)2419Prefixes.emplace_back(p.second);2420return;2421}24222423// For Linux, if --sysroot is not specified, look for RHEL/CentOS devtoolsets2424// and gcc-toolsets.2425if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&2426D.getVFS().exists("/opt/rh")) {2427// TODO: We may want to remove this, since the functionality2428// can be achieved using config files.2429Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr");2430Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");2431Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");2432Prefixes.push_back("/opt/rh/devtoolset-12/root/usr");2433Prefixes.push_back("/opt/rh/devtoolset-11/root/usr");2434Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");2435Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");2436Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");2437Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");2438Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");2439Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");2440Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");2441Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");2442}24432444// Fall back to /usr which is used by most non-Solaris systems.2445Prefixes.push_back(concat(SysRoot, "/usr"));2446}24472448/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(2449const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,2450SmallVectorImpl<StringRef> &LibDirs,2451SmallVectorImpl<StringRef> &TripleAliases,2452SmallVectorImpl<StringRef> &BiarchLibDirs,2453SmallVectorImpl<StringRef> &BiarchTripleAliases) {2454// Declare a bunch of static data sets that we'll select between below. These2455// are specifically designed to always refer to string literals to avoid any2456// lifetime or initialization issues.2457//2458// The *Triples variables hard code some triples so that, for example,2459// --target=aarch64 (incomplete triple) can detect lib/aarch64-linux-gnu.2460// They are not needed when the user has correct LLVM_DEFAULT_TARGET_TRIPLE2461// and always uses the full --target (e.g. --target=aarch64-linux-gnu). The2462// lists should shrink over time. Please don't add more elements to *Triples.2463static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};2464static const char *const AArch64Triples[] = {2465"aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",2466"aarch64-suse-linux"};2467static const char *const AArch64beLibDirs[] = {"/lib"};2468static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu"};24692470static const char *const ARMLibDirs[] = {"/lib"};2471static const char *const ARMTriples[] = {"arm-linux-gnueabi"};2472static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",2473"armv7hl-redhat-linux-gnueabi",2474"armv6hl-suse-linux-gnueabi",2475"armv7hl-suse-linux-gnueabi"};2476static const char *const ARMebLibDirs[] = {"/lib"};2477static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};2478static const char *const ARMebHFTriples[] = {2479"armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};24802481static const char *const AVRLibDirs[] = {"/lib"};2482static const char *const AVRTriples[] = {"avr"};24832484static const char *const CSKYLibDirs[] = {"/lib"};2485static const char *const CSKYTriples[] = {2486"csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};24872488static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};2489static const char *const X86_64Triples[] = {2490"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",2491"x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",2492"x86_64-redhat-linux", "x86_64-suse-linux",2493"x86_64-manbo-linux-gnu", "x86_64-slackware-linux",2494"x86_64-unknown-linux", "x86_64-amazon-linux"};2495static const char *const X32Triples[] = {"x86_64-linux-gnux32",2496"x86_64-pc-linux-gnux32"};2497static const char *const X32LibDirs[] = {"/libx32", "/lib"};2498static const char *const X86LibDirs[] = {"/lib32", "/lib"};2499static const char *const X86Triples[] = {2500"i586-linux-gnu", "i686-linux-gnu", "i686-pc-linux-gnu",2501"i386-redhat-linux6E", "i686-redhat-linux", "i386-redhat-linux",2502"i586-suse-linux", "i686-montavista-linux",2503};25042505static const char *const LoongArch64LibDirs[] = {"/lib64", "/lib"};2506static const char *const LoongArch64Triples[] = {2507"loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"};25082509static const char *const M68kLibDirs[] = {"/lib"};2510static const char *const M68kTriples[] = {"m68k-unknown-linux-gnu",2511"m68k-suse-linux"};25122513static const char *const MIPSLibDirs[] = {"/libo32", "/lib"};2514static const char *const MIPSTriples[] = {2515"mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",2516"mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};2517static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"};2518static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",2519"mips-img-linux-gnu"};25202521static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};2522static const char *const MIPS64Triples[] = {2523"mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64-linux-gnuabi64",2524"mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};2525static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};2526static const char *const MIPS64ELTriples[] = {2527"mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64el-linux-gnuabi64",2528"mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"};25292530static const char *const MIPSN32LibDirs[] = {"/lib32"};2531static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",2532"mipsisa64r6-linux-gnuabin32"};2533static const char *const MIPSN32ELLibDirs[] = {"/lib32"};2534static const char *const MIPSN32ELTriples[] = {2535"mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"};25362537static const char *const MSP430LibDirs[] = {"/lib"};2538static const char *const MSP430Triples[] = {"msp430-elf"};25392540static const char *const PPCLibDirs[] = {"/lib32", "/lib"};2541static const char *const PPCTriples[] = {2542"powerpc-unknown-linux-gnu",2543// On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a2544// 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".2545"powerpc64-suse-linux", "powerpc-montavista-linuxspe"};2546static const char *const PPCLELibDirs[] = {"/lib32", "/lib"};2547static const char *const PPCLETriples[] = {"powerpcle-unknown-linux-gnu",2548"powerpcle-linux-musl"};25492550static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};2551static const char *const PPC64Triples[] = {"powerpc64-unknown-linux-gnu",2552"powerpc64-suse-linux",2553"ppc64-redhat-linux"};2554static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"};2555static const char *const PPC64LETriples[] = {2556"powerpc64le-unknown-linux-gnu", "powerpc64le-none-linux-gnu",2557"powerpc64le-suse-linux", "ppc64le-redhat-linux"};25582559static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"};2560static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",2561"riscv32-unknown-elf"};2562static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};2563static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",2564"riscv64-unknown-elf"};25652566static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};2567static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",2568"sparcv8-linux-gnu"};2569static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};2570static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",2571"sparcv9-linux-gnu"};25722573static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};2574static const char *const SystemZTriples[] = {2575"s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux",2576"s390x-redhat-linux"};25772578using std::begin;2579using std::end;25802581if (TargetTriple.isOSSolaris()) {2582static const char *const SolarisLibDirs[] = {"/lib"};2583static const char *const SolarisSparcV8Triples[] = {2584"sparc-sun-solaris2.11"};2585static const char *const SolarisSparcV9Triples[] = {2586"sparcv9-sun-solaris2.11"};2587static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11"};2588static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11"};2589LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));2590BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));2591switch (TargetTriple.getArch()) {2592case llvm::Triple::x86:2593TripleAliases.append(begin(SolarisX86Triples), end(SolarisX86Triples));2594BiarchTripleAliases.append(begin(SolarisX86_64Triples),2595end(SolarisX86_64Triples));2596break;2597case llvm::Triple::x86_64:2598TripleAliases.append(begin(SolarisX86_64Triples),2599end(SolarisX86_64Triples));2600BiarchTripleAliases.append(begin(SolarisX86Triples),2601end(SolarisX86Triples));2602break;2603case llvm::Triple::sparc:2604TripleAliases.append(begin(SolarisSparcV8Triples),2605end(SolarisSparcV8Triples));2606BiarchTripleAliases.append(begin(SolarisSparcV9Triples),2607end(SolarisSparcV9Triples));2608break;2609case llvm::Triple::sparcv9:2610TripleAliases.append(begin(SolarisSparcV9Triples),2611end(SolarisSparcV9Triples));2612BiarchTripleAliases.append(begin(SolarisSparcV8Triples),2613end(SolarisSparcV8Triples));2614break;2615default:2616break;2617}2618return;2619}26202621// Android targets should not use GNU/Linux tools or libraries.2622if (TargetTriple.isAndroid()) {2623static const char *const AArch64AndroidTriples[] = {2624"aarch64-linux-android"};2625static const char *const ARMAndroidTriples[] = {"arm-linux-androideabi"};2626static const char *const X86AndroidTriples[] = {"i686-linux-android"};2627static const char *const X86_64AndroidTriples[] = {"x86_64-linux-android"};26282629switch (TargetTriple.getArch()) {2630case llvm::Triple::aarch64:2631LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));2632TripleAliases.append(begin(AArch64AndroidTriples),2633end(AArch64AndroidTriples));2634break;2635case llvm::Triple::arm:2636case llvm::Triple::thumb:2637LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));2638TripleAliases.append(begin(ARMAndroidTriples), end(ARMAndroidTriples));2639break;2640case llvm::Triple::x86_64:2641LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2642TripleAliases.append(begin(X86_64AndroidTriples),2643end(X86_64AndroidTriples));2644BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));2645BiarchTripleAliases.append(begin(X86AndroidTriples),2646end(X86AndroidTriples));2647break;2648case llvm::Triple::x86:2649LibDirs.append(begin(X86LibDirs), end(X86LibDirs));2650TripleAliases.append(begin(X86AndroidTriples), end(X86AndroidTriples));2651BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2652BiarchTripleAliases.append(begin(X86_64AndroidTriples),2653end(X86_64AndroidTriples));2654break;2655default:2656break;2657}26582659return;2660}26612662if (TargetTriple.isOSHurd()) {2663switch (TargetTriple.getArch()) {2664case llvm::Triple::x86_64:2665LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2666TripleAliases.push_back("x86_64-gnu");2667break;2668case llvm::Triple::x86:2669LibDirs.append(begin(X86LibDirs), end(X86LibDirs));2670TripleAliases.push_back("i686-gnu");2671break;2672default:2673break;2674}26752676return;2677}26782679switch (TargetTriple.getArch()) {2680case llvm::Triple::aarch64:2681LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));2682TripleAliases.append(begin(AArch64Triples), end(AArch64Triples));2683BiarchLibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));2684BiarchTripleAliases.append(begin(AArch64Triples), end(AArch64Triples));2685break;2686case llvm::Triple::aarch64_be:2687LibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));2688TripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));2689BiarchLibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs));2690BiarchTripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples));2691break;2692case llvm::Triple::arm:2693case llvm::Triple::thumb:2694LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));2695if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||2696TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||2697TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||2698TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {2699TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));2700} else {2701TripleAliases.append(begin(ARMTriples), end(ARMTriples));2702}2703break;2704case llvm::Triple::armeb:2705case llvm::Triple::thumbeb:2706LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));2707if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||2708TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||2709TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||2710TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {2711TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));2712} else {2713TripleAliases.append(begin(ARMebTriples), end(ARMebTriples));2714}2715break;2716case llvm::Triple::avr:2717LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));2718TripleAliases.append(begin(AVRTriples), end(AVRTriples));2719break;2720case llvm::Triple::csky:2721LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));2722TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));2723break;2724case llvm::Triple::x86_64:2725if (TargetTriple.isX32()) {2726LibDirs.append(begin(X32LibDirs), end(X32LibDirs));2727TripleAliases.append(begin(X32Triples), end(X32Triples));2728BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2729BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));2730} else {2731LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2732TripleAliases.append(begin(X86_64Triples), end(X86_64Triples));2733BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));2734BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));2735}2736BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));2737BiarchTripleAliases.append(begin(X86Triples), end(X86Triples));2738break;2739case llvm::Triple::x86:2740LibDirs.append(begin(X86LibDirs), end(X86LibDirs));2741// MCU toolchain is 32 bit only and its triple alias is TargetTriple2742// itself, which will be appended below.2743if (!TargetTriple.isOSIAMCU()) {2744TripleAliases.append(begin(X86Triples), end(X86Triples));2745BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));2746BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));2747BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));2748BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));2749}2750break;2751// TODO: Handle loongarch32.2752case llvm::Triple::loongarch64:2753LibDirs.append(begin(LoongArch64LibDirs), end(LoongArch64LibDirs));2754TripleAliases.append(begin(LoongArch64Triples), end(LoongArch64Triples));2755break;2756case llvm::Triple::m68k:2757LibDirs.append(begin(M68kLibDirs), end(M68kLibDirs));2758TripleAliases.append(begin(M68kTriples), end(M68kTriples));2759break;2760case llvm::Triple::mips:2761LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));2762TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));2763BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));2764BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));2765BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));2766BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));2767break;2768case llvm::Triple::mipsel:2769LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));2770TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));2771TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));2772BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));2773BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));2774BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));2775BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));2776break;2777case llvm::Triple::mips64:2778LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));2779TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));2780BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));2781BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));2782BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));2783BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));2784break;2785case llvm::Triple::mips64el:2786LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));2787TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));2788BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));2789BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));2790BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));2791BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));2792BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));2793break;2794case llvm::Triple::msp430:2795LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs));2796TripleAliases.append(begin(MSP430Triples), end(MSP430Triples));2797break;2798case llvm::Triple::ppc:2799LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));2800TripleAliases.append(begin(PPCTriples), end(PPCTriples));2801BiarchLibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));2802BiarchTripleAliases.append(begin(PPC64Triples), end(PPC64Triples));2803break;2804case llvm::Triple::ppcle:2805LibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));2806TripleAliases.append(begin(PPCLETriples), end(PPCLETriples));2807BiarchLibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));2808BiarchTripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));2809break;2810case llvm::Triple::ppc64:2811LibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs));2812TripleAliases.append(begin(PPC64Triples), end(PPC64Triples));2813BiarchLibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));2814BiarchTripleAliases.append(begin(PPCTriples), end(PPCTriples));2815break;2816case llvm::Triple::ppc64le:2817LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));2818TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));2819BiarchLibDirs.append(begin(PPCLELibDirs), end(PPCLELibDirs));2820BiarchTripleAliases.append(begin(PPCLETriples), end(PPCLETriples));2821break;2822case llvm::Triple::riscv32:2823LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));2824TripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));2825BiarchLibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));2826BiarchTripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));2827break;2828case llvm::Triple::riscv64:2829LibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs));2830TripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples));2831BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));2832BiarchTripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples));2833break;2834case llvm::Triple::sparc:2835case llvm::Triple::sparcel:2836LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));2837TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));2838BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));2839BiarchTripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));2840break;2841case llvm::Triple::sparcv9:2842LibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));2843TripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples));2844BiarchLibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));2845BiarchTripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));2846break;2847case llvm::Triple::systemz:2848LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs));2849TripleAliases.append(begin(SystemZTriples), end(SystemZTriples));2850break;2851default:2852// By default, just rely on the standard lib directories and the original2853// triple.2854break;2855}28562857// Also include the multiarch variant if it's different.2858if (TargetTriple.str() != BiarchTriple.str())2859BiarchTripleAliases.push_back(BiarchTriple.str());2860}28612862bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(2863const llvm::Triple &TargetTriple, const ArgList &Args,2864StringRef Path, bool NeedsBiarchSuffix) {2865llvm::Triple::ArchType TargetArch = TargetTriple.getArch();2866DetectedMultilibs Detected;28672868// Android standalone toolchain could have multilibs for ARM and Thumb.2869// Debian mips multilibs behave more like the rest of the biarch ones,2870// so handle them there2871if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {2872// It should also work without multilibs in a simplified toolchain.2873findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);2874} else if (TargetTriple.isCSKY()) {2875findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);2876} else if (TargetTriple.isMIPS()) {2877if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))2878return false;2879} else if (TargetTriple.isRISCV()) {2880findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);2881} else if (isMSP430(TargetArch)) {2882findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);2883} else if (TargetArch == llvm::Triple::avr) {2884// AVR has no multilibs.2885} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,2886NeedsBiarchSuffix, Detected)) {2887return false;2888}28892890Multilibs = Detected.Multilibs;2891SelectedMultilib = Detected.SelectedMultilibs.empty()2892? Multilib()2893: Detected.SelectedMultilibs.back();2894BiarchSibling = Detected.BiarchSibling;28952896return true;2897}28982899void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(2900const llvm::Triple &TargetTriple, const ArgList &Args,2901const std::string &LibDir, StringRef CandidateTriple,2902bool NeedsBiarchSuffix, bool GCCDirExists, bool GCCCrossDirExists) {2903// Locations relative to the system lib directory where GCC's triple-specific2904// directories might reside.2905struct GCCLibSuffix {2906// Path from system lib directory to GCC triple-specific directory.2907std::string LibSuffix;2908// Path from GCC triple-specific directory back to system lib directory.2909// This is one '..' component per component in LibSuffix.2910StringRef ReversePath;2911// Whether this library suffix is relevant for the triple.2912bool Active;2913} Suffixes[] = {2914// This is the normal place.2915{"gcc/" + CandidateTriple.str(), "../..", GCCDirExists},29162917// Debian puts cross-compilers in gcc-cross.2918{"gcc-cross/" + CandidateTriple.str(), "../..", GCCCrossDirExists},29192920// The Freescale PPC SDK has the gcc libraries in2921// <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do2922// this on Freescale triples, though, since some systems put a *lot* of2923// files in that location, not just GCC installation data.2924{CandidateTriple.str(), "..",2925TargetTriple.getVendor() == llvm::Triple::Freescale ||2926TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};29272928for (auto &Suffix : Suffixes) {2929if (!Suffix.Active)2930continue;29312932StringRef LibSuffix = Suffix.LibSuffix;2933std::error_code EC;2934for (llvm::vfs::directory_iterator2935LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),2936LE;2937!EC && LI != LE; LI = LI.increment(EC)) {2938StringRef VersionText = llvm::sys::path::filename(LI->path());2939GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);2940if (CandidateVersion.Major != -1) // Filter obviously bad entries.2941if (!CandidateGCCInstallPaths.insert(std::string(LI->path())).second)2942continue; // Saw this path before; no need to look at it again.2943if (CandidateVersion.isOlderThan(4, 1, 1))2944continue;2945if (CandidateVersion <= Version)2946continue;29472948if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),2949NeedsBiarchSuffix))2950continue;29512952Version = CandidateVersion;2953GCCTriple.setTriple(CandidateTriple);2954// FIXME: We hack together the directory name here instead of2955// using LI to ensure stable path separators across Windows and2956// Linux.2957GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();2958GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();2959IsValid = true;2960}2961}2962}29632964bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(2965const llvm::Triple &TargetTriple, const ArgList &Args,2966const SmallVectorImpl<StringRef> &CandidateTriples,2967const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {2968if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))2969return false;29702971for (StringRef CandidateTriple : CandidateTriples) {2972if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple))2973return true;2974}29752976for (StringRef CandidateTriple : CandidateBiarchTriples) {2977if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true))2978return true;2979}2980return false;2981}29822983bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(2984const llvm::Triple &TargetTriple, const ArgList &Args,2985StringRef CandidateTriple, bool NeedsBiarchSuffix) {2986llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =2987D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,2988"/config-" + CandidateTriple.str()));2989if (File) {2990SmallVector<StringRef, 2> Lines;2991File.get()->getBuffer().split(Lines, "\n");2992for (StringRef Line : Lines) {2993Line = Line.trim();2994// CURRENT=triple-version2995if (!Line.consume_front("CURRENT="))2996continue;2997// Process the config file pointed to by CURRENT.2998llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =2999D.getVFS().getBufferForFile(3000concat(D.SysRoot, GentooConfigDir, "/" + Line));3001std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');3002// List of paths to scan for libraries.3003SmallVector<StringRef, 4> GentooScanPaths;3004// Scan the Config file to find installed GCC libraries path.3005// Typical content of the GCC config file:3006// LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x:/usr/lib/gcc/3007// (continued from previous line) x86_64-pc-linux-gnu/4.9.x/32"3008// MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/man"3009// INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.x/info"3010// STDCXX_INCDIR="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.x/include/g++-v4"3011// We are looking for the paths listed in LDPATH=... .3012if (ConfigFile) {3013SmallVector<StringRef, 2> ConfigLines;3014ConfigFile.get()->getBuffer().split(ConfigLines, "\n");3015for (StringRef ConfLine : ConfigLines) {3016ConfLine = ConfLine.trim();3017if (ConfLine.consume_front("LDPATH=")) {3018// Drop '"' from front and back if present.3019ConfLine.consume_back("\"");3020ConfLine.consume_front("\"");3021// Get all paths sperated by ':'3022ConfLine.split(GentooScanPaths, ':', -1, /*AllowEmpty*/ false);3023}3024}3025}3026// Test the path based on the version in /etc/env.d/gcc/config-{tuple}.3027std::string basePath = "/usr/lib/gcc/" + ActiveVersion.first.str() + "/"3028+ ActiveVersion.second.str();3029GentooScanPaths.push_back(StringRef(basePath));30303031// Scan all paths for GCC libraries.3032for (const auto &GentooScanPath : GentooScanPaths) {3033std::string GentooPath = concat(D.SysRoot, GentooScanPath);3034if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {3035if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,3036NeedsBiarchSuffix))3037continue;30383039Version = GCCVersion::Parse(ActiveVersion.second);3040GCCInstallPath = GentooPath;3041GCCParentLibPath = GentooPath + std::string("/../../..");3042GCCTriple.setTriple(ActiveVersion.first);3043IsValid = true;3044return true;3045}3046}3047}3048}30493050return false;3051}30523053Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,3054const ArgList &Args)3055: ToolChain(D, Triple, Args), GCCInstallation(D),3056CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {3057getProgramPaths().push_back(getDriver().Dir);3058}30593060Generic_GCC::~Generic_GCC() {}30613062Tool *Generic_GCC::getTool(Action::ActionClass AC) const {3063switch (AC) {3064case Action::PreprocessJobClass:3065if (!Preprocess)3066Preprocess.reset(new clang::driver::tools::gcc::Preprocessor(*this));3067return Preprocess.get();3068case Action::CompileJobClass:3069if (!Compile)3070Compile.reset(new tools::gcc::Compiler(*this));3071return Compile.get();3072default:3073return ToolChain::getTool(AC);3074}3075}30763077Tool *Generic_GCC::buildAssembler() const {3078return new tools::gnutools::Assembler(*this);3079}30803081Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }30823083void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {3084// Print the information about how we detected the GCC installation.3085GCCInstallation.print(OS);3086CudaInstallation->print(OS);3087RocmInstallation->print(OS);3088}30893090ToolChain::UnwindTableLevel3091Generic_GCC::getDefaultUnwindTableLevel(const ArgList &Args) const {3092switch (getArch()) {3093case llvm::Triple::aarch64:3094case llvm::Triple::aarch64_be:3095case llvm::Triple::ppc:3096case llvm::Triple::ppcle:3097case llvm::Triple::ppc64:3098case llvm::Triple::ppc64le:3099case llvm::Triple::riscv32:3100case llvm::Triple::riscv64:3101case llvm::Triple::x86:3102case llvm::Triple::x86_64:3103return UnwindTableLevel::Asynchronous;3104default:3105return UnwindTableLevel::None;3106}3107}31083109bool Generic_GCC::isPICDefault() const {3110switch (getArch()) {3111case llvm::Triple::x86_64:3112return getTriple().isOSWindows();3113case llvm::Triple::mips64:3114case llvm::Triple::mips64el:3115return true;3116default:3117return false;3118}3119}31203121bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const {3122return false;3123}31243125bool Generic_GCC::isPICDefaultForced() const {3126return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();3127}31283129bool Generic_GCC::IsIntegratedAssemblerDefault() const {3130switch (getTriple().getArch()) {3131case llvm::Triple::nvptx:3132case llvm::Triple::nvptx64:3133case llvm::Triple::xcore:3134return false;3135default:3136return true;3137}3138}31393140void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {3141// Cross-compiling binutils and GCC installations (vanilla and openSUSE at3142// least) put various tools in a triple-prefixed directory off of the parent3143// of the GCC installation. We use the GCC triple here to ensure that we end3144// up with tools that support the same amount of cross compiling as the3145// detected GCC installation. For example, if we find a GCC installation3146// targeting x86_64, but it is a bi-arch GCC installation, it can also be3147// used to target i386.3148if (GCCInstallation.isValid()) {3149PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +3150GCCInstallation.getTriple().str() + "/bin")3151.str());3152}3153}31543155void Generic_GCC::AddMultilibPaths(const Driver &D,3156const std::string &SysRoot,3157const std::string &OSLibDir,3158const std::string &MultiarchTriple,3159path_list &Paths) {3160// Add the multilib suffixed paths where they are available.3161if (GCCInstallation.isValid()) {3162assert(!SelectedMultilibs.empty());3163const llvm::Triple &GCCTriple = GCCInstallation.getTriple();3164const std::string &LibPath =3165std::string(GCCInstallation.getParentLibPath());31663167// Sourcery CodeBench MIPS toolchain holds some libraries under3168// a biarch-like suffix of the GCC installation.3169if (const auto &PathsCallback = Multilibs.filePathsCallback())3170for (const auto &Path : PathsCallback(SelectedMultilibs.back()))3171addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);31723173// Add lib/gcc/$triple/$version, with an optional /multilib suffix.3174addPathIfExists(D,3175GCCInstallation.getInstallPath() +3176SelectedMultilibs.back().gccSuffix(),3177Paths);31783179// Add lib/gcc/$triple/$libdir3180// For GCC built with --enable-version-specific-runtime-libs.3181addPathIfExists(D, GCCInstallation.getInstallPath() + "/../" + OSLibDir,3182Paths);31833184// GCC cross compiling toolchains will install target libraries which ship3185// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as3186// any part of the GCC installation in3187// <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat3188// debatable, but is the reality today. We need to search this tree even3189// when we have a sysroot somewhere else. It is the responsibility of3190// whomever is doing the cross build targeting a sysroot using a GCC3191// installation that is *not* within the system root to ensure two things:3192//3193// 1) Any DSOs that are linked in from this tree or from the install path3194// above must be present on the system root and found via an3195// appropriate rpath.3196// 2) There must not be libraries installed into3197// <prefix>/<triple>/<libdir> unless they should be preferred over3198// those within the system root.3199//3200// Note that this matches the GCC behavior. See the below comment for where3201// Clang diverges from GCC's behavior.3202addPathIfExists(D,3203LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +3204SelectedMultilibs.back().osSuffix(),3205Paths);32063207// If the GCC installation we found is inside of the sysroot, we want to3208// prefer libraries installed in the parent prefix of the GCC installation.3209// It is important to *not* use these paths when the GCC installation is3210// outside of the system root as that can pick up unintended libraries.3211// This usually happens when there is an external cross compiler on the3212// host system, and a more minimal sysroot available that is the target of3213// the cross. Note that GCC does include some of these directories in some3214// configurations but this seems somewhere between questionable and simply3215// a bug.3216if (StringRef(LibPath).starts_with(SysRoot))3217addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);3218}3219}32203221void Generic_GCC::AddMultiarchPaths(const Driver &D,3222const std::string &SysRoot,3223const std::string &OSLibDir,3224path_list &Paths) {3225if (GCCInstallation.isValid()) {3226const std::string &LibPath =3227std::string(GCCInstallation.getParentLibPath());3228const llvm::Triple &GCCTriple = GCCInstallation.getTriple();3229const Multilib &Multilib = GCCInstallation.getMultilib();3230addPathIfExists(3231D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),3232Paths);3233}3234}32353236void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,3237ArgStringList &CC1Args) const {3238// Add include directories specific to the selected multilib set and multilib.3239if (!GCCInstallation.isValid())3240return;3241// gcc TOOL_INCLUDE_DIR.3242const llvm::Triple &GCCTriple = GCCInstallation.getTriple();3243std::string LibPath(GCCInstallation.getParentLibPath());3244addSystemInclude(DriverArgs, CC1Args,3245Twine(LibPath) + "/../" + GCCTriple.str() + "/include");32463247const auto &Callback = Multilibs.includeDirsCallback();3248if (Callback) {3249for (const auto &Path : Callback(GCCInstallation.getMultilib()))3250addExternCSystemIncludeIfExists(DriverArgs, CC1Args,3251GCCInstallation.getInstallPath() + Path);3252}3253}32543255void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,3256ArgStringList &CC1Args) const {3257if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,3258options::OPT_nostdlibinc))3259return;32603261switch (GetCXXStdlibType(DriverArgs)) {3262case ToolChain::CST_Libcxx:3263addLibCxxIncludePaths(DriverArgs, CC1Args);3264break;32653266case ToolChain::CST_Libstdcxx:3267addLibStdCxxIncludePaths(DriverArgs, CC1Args);3268break;3269}3270}32713272void3273Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,3274llvm::opt::ArgStringList &CC1Args) const {3275const Driver &D = getDriver();3276std::string SysRoot = computeSysRoot();3277if (SysRoot.empty())3278SysRoot = llvm::sys::path::get_separator();32793280auto AddIncludePath = [&](StringRef Path, bool TargetDirRequired = false) {3281std::string Version = detectLibcxxVersion(Path);3282if (Version.empty())3283return false;32843285// First add the per-target include path if it exists.3286bool TargetDirExists = false;3287std::optional<std::string> TargetIncludeDir = getTargetSubDirPath(Path);3288if (TargetIncludeDir) {3289SmallString<128> TargetDir(*TargetIncludeDir);3290llvm::sys::path::append(TargetDir, "c++", Version);3291if (D.getVFS().exists(TargetDir)) {3292addSystemInclude(DriverArgs, CC1Args, TargetDir);3293TargetDirExists = true;3294}3295}3296if (TargetDirRequired && !TargetDirExists)3297return false;32983299// Second add the generic one.3300SmallString<128> GenericDir(Path);3301llvm::sys::path::append(GenericDir, "c++", Version);3302addSystemInclude(DriverArgs, CC1Args, GenericDir);3303return true;3304};33053306// Android only uses the libc++ headers installed alongside the toolchain if3307// they contain an Android-specific target include path, otherwise they're3308// incompatible with the NDK libraries.3309SmallString<128> DriverIncludeDir(getDriver().Dir);3310llvm::sys::path::append(DriverIncludeDir, "..", "include");3311if (AddIncludePath(DriverIncludeDir,3312/*TargetDirRequired=*/getTriple().isAndroid()))3313return;3314// If this is a development, non-installed, clang, libcxx will3315// not be found at ../include/c++ but it likely to be found at3316// one of the following two locations:3317SmallString<128> UsrLocalIncludeDir(SysRoot);3318llvm::sys::path::append(UsrLocalIncludeDir, "usr", "local", "include");3319if (AddIncludePath(UsrLocalIncludeDir))3320return;3321SmallString<128> UsrIncludeDir(SysRoot);3322llvm::sys::path::append(UsrIncludeDir, "usr", "include");3323if (AddIncludePath(UsrIncludeDir))3324return;3325}33263327bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,3328Twine IncludeSuffix,3329const llvm::opt::ArgList &DriverArgs,3330llvm::opt::ArgStringList &CC1Args,3331bool DetectDebian) const {3332if (!getVFS().exists(IncludeDir))3333return false;33343335// Debian native gcc uses g++-multiarch-incdir.diff which uses3336// include/x86_64-linux-gnu/c++/10$IncludeSuffix instead of3337// include/c++/10/x86_64-linux-gnu$IncludeSuffix.3338std::string Dir = IncludeDir.str();3339StringRef Include =3340llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));3341std::string Path =3342(Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)3343.str();3344if (DetectDebian && !getVFS().exists(Path))3345return false;33463347// GPLUSPLUS_INCLUDE_DIR3348addSystemInclude(DriverArgs, CC1Args, IncludeDir);3349// GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent3350// include directory.3351if (DetectDebian)3352addSystemInclude(DriverArgs, CC1Args, Path);3353else if (!Triple.empty())3354addSystemInclude(DriverArgs, CC1Args,3355IncludeDir + "/" + Triple + IncludeSuffix);3356// GPLUSPLUS_BACKWARD_INCLUDE_DIR3357addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");3358return true;3359}33603361bool Generic_GCC::addGCCLibStdCxxIncludePaths(3362const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,3363StringRef DebianMultiarch) const {3364assert(GCCInstallation.isValid());33653366// By default, look for the C++ headers in an include directory adjacent to3367// the lib directory of the GCC installation. Note that this is expect to be3368// equivalent to '/usr/include/c++/X.Y' in almost all cases.3369StringRef LibDir = GCCInstallation.getParentLibPath();3370StringRef InstallDir = GCCInstallation.getInstallPath();3371StringRef TripleStr = GCCInstallation.getTriple().str();3372const Multilib &Multilib = GCCInstallation.getMultilib();3373const GCCVersion &Version = GCCInstallation.getVersion();33743375// Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).3376if (addLibStdCXXIncludePaths(3377LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,3378TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))3379return true;33803381// Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not3382// empty). Like above but for GCC built with3383// --enable-version-specific-runtime-libs.3384if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +3385Version.Text + "/include/c++/",3386TripleStr, Multilib.includeSuffix(), DriverArgs,3387CC1Args))3388return true;33893390// Detect Debian g++-multiarch-incdir.diff.3391if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,3392DebianMultiarch, Multilib.includeSuffix(),3393DriverArgs, CC1Args, /*Debian=*/true))3394return true;33953396// Try /../include/c++/$version (gcc --print-multiarch is empty).3397if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,3398TripleStr, Multilib.includeSuffix(), DriverArgs,3399CC1Args))3400return true;34013402// Otherwise, fall back on a bunch of options which don't use multiarch3403// layouts for simplicity.3404const std::string LibStdCXXIncludePathCandidates[] = {3405// Gentoo is weird and places its headers inside the GCC install,3406// so if the first attempt to find the headers fails, try these patterns.3407InstallDir.str() + "/include/g++-v" + Version.Text,3408InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +3409Version.MinorStr,3410InstallDir.str() + "/include/g++-v" + Version.MajorStr,3411};34123413for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {3414if (addLibStdCXXIncludePaths(IncludePath, TripleStr,3415Multilib.includeSuffix(), DriverArgs, CC1Args))3416return true;3417}3418return false;3419}34203421void3422Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,3423llvm::opt::ArgStringList &CC1Args) const {3424if (GCCInstallation.isValid()) {3425addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,3426GCCInstallation.getTriple().str());3427}3428}34293430llvm::opt::DerivedArgList *3431Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,3432Action::OffloadKind DeviceOffloadKind) const {34333434// If this tool chain is used for an OpenMP offloading device we have to make3435// sure we always generate a shared library regardless of the commands the3436// user passed to the host. This is required because the runtime library3437// is required to load the device image dynamically at run time.3438if (DeviceOffloadKind == Action::OFK_OpenMP) {3439DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());3440const OptTable &Opts = getDriver().getOpts();34413442// Request the shared library. Given that these options are decided3443// implicitly, they do not refer to any base argument.3444DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_shared));3445DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_fPIC));34463447// Filter all the arguments we don't care passing to the offloading3448// toolchain as they can mess up with the creation of a shared library.3449for (auto *A : Args) {3450switch ((options::ID)A->getOption().getID()) {3451default:3452DAL->append(A);3453break;3454case options::OPT_shared:3455case options::OPT_dynamic:3456case options::OPT_static:3457case options::OPT_fPIC:3458case options::OPT_fno_PIC:3459case options::OPT_fpic:3460case options::OPT_fno_pic:3461case options::OPT_fPIE:3462case options::OPT_fno_PIE:3463case options::OPT_fpie:3464case options::OPT_fno_pie:3465break;3466}3467}3468return DAL;3469}3470return nullptr;3471}34723473void Generic_ELF::anchor() {}34743475void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,3476ArgStringList &CC1Args,3477Action::OffloadKind) const {3478if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,3479options::OPT_fno_use_init_array, true))3480CC1Args.push_back("-fno-use-init-array");3481}348234833484