10b57cec5SDimitry Andric //===--- Fuchsia.cpp - Fuchsia ToolChain Implementations --------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Fuchsia.h" 100b57cec5SDimitry Andric #include "CommonArgs.h" 110b57cec5SDimitry Andric #include "clang/Config/config.h" 120b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 130b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 140b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 1506c3fb27SDimitry Andric #include "clang/Driver/MultilibBuilder.h" 160b57cec5SDimitry Andric #include "clang/Driver/Options.h" 170b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 180b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 195ffd83dbSDimitry Andric #include "llvm/ProfileData/InstrProf.h" 200b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 210b57cec5SDimitry Andric #include "llvm/Support/Path.h" 220b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace clang::driver; 250b57cec5SDimitry Andric using namespace clang::driver::toolchains; 260b57cec5SDimitry Andric using namespace clang::driver::tools; 270b57cec5SDimitry Andric using namespace clang; 280b57cec5SDimitry Andric using namespace llvm::opt; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using tools::addMultilibFlag; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, 330b57cec5SDimitry Andric const InputInfo &Output, 340b57cec5SDimitry Andric const InputInfoList &Inputs, 350b57cec5SDimitry Andric const ArgList &Args, 360b57cec5SDimitry Andric const char *LinkingOutput) const { 375f757f3fSDimitry Andric const auto &ToolChain = static_cast<const Fuchsia &>(getToolChain()); 380b57cec5SDimitry Andric const Driver &D = ToolChain.getDriver(); 390b57cec5SDimitry Andric 4081ad6265SDimitry Andric const llvm::Triple &Triple = ToolChain.getEffectiveTriple(); 4181ad6265SDimitry Andric 420b57cec5SDimitry Andric ArgStringList CmdArgs; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 450b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 460b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 470b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 480b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 490b57cec5SDimitry Andric // handled somewhere else. 500b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 510b57cec5SDimitry Andric 52480093f4SDimitry Andric CmdArgs.push_back("-z"); 535ffd83dbSDimitry Andric CmdArgs.push_back("max-page-size=4096"); 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric CmdArgs.push_back("-z"); 56480093f4SDimitry Andric CmdArgs.push_back("now"); 57480093f4SDimitry Andric 585f757f3fSDimitry Andric CmdArgs.push_back("-z"); 595f757f3fSDimitry Andric CmdArgs.push_back("start-stop-visibility=hidden"); 605f757f3fSDimitry Andric 610b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 62fe6060f1SDimitry Andric if (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") || 63fe6060f1SDimitry Andric llvm::sys::path::stem(Exec).equals_insensitive("ld.lld")) { 640b57cec5SDimitry Andric CmdArgs.push_back("-z"); 650b57cec5SDimitry Andric CmdArgs.push_back("rodynamic"); 66a7dea167SDimitry Andric CmdArgs.push_back("-z"); 67a7dea167SDimitry Andric CmdArgs.push_back("separate-loadable-segments"); 68349cc55cSDimitry Andric CmdArgs.push_back("-z"); 69349cc55cSDimitry Andric CmdArgs.push_back("rel"); 705ffd83dbSDimitry Andric CmdArgs.push_back("--pack-dyn-relocs=relr"); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric if (!D.SysRoot.empty()) 740b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) 770b57cec5SDimitry Andric CmdArgs.push_back("-pie"); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric if (Args.hasArg(options::OPT_rdynamic)) 800b57cec5SDimitry Andric CmdArgs.push_back("-export-dynamic"); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric if (Args.hasArg(options::OPT_s)) 830b57cec5SDimitry Andric CmdArgs.push_back("-s"); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric if (Args.hasArg(options::OPT_r)) { 860b57cec5SDimitry Andric CmdArgs.push_back("-r"); 870b57cec5SDimitry Andric } else { 880b57cec5SDimitry Andric CmdArgs.push_back("--build-id"); 890b57cec5SDimitry Andric CmdArgs.push_back("--hash-style=gnu"); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 9281ad6265SDimitry Andric if (ToolChain.getArch() == llvm::Triple::aarch64) { 93bdd1243dSDimitry Andric CmdArgs.push_back("--execute-only"); 94bdd1243dSDimitry Andric 9581ad6265SDimitry Andric std::string CPU = getCPUName(D, Args, Triple); 9681ad6265SDimitry Andric if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53") 9781ad6265SDimitry Andric CmdArgs.push_back("--fix-cortex-a53-843419"); 9881ad6265SDimitry Andric } 9981ad6265SDimitry Andric 1000b57cec5SDimitry Andric CmdArgs.push_back("--eh-frame-hdr"); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 1030b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 1040b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_shared)) 1050b57cec5SDimitry Andric CmdArgs.push_back("-shared"); 1060b57cec5SDimitry Andric 107349cc55cSDimitry Andric const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args); 1080b57cec5SDimitry Andric 109fcaf7f86SDimitry Andric if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) { 1100b57cec5SDimitry Andric std::string Dyld = D.DyldPrefix; 1110b57cec5SDimitry Andric if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt()) 1120b57cec5SDimitry Andric Dyld += "asan/"; 113fe6060f1SDimitry Andric if (SanArgs.needsHwasanRt() && SanArgs.needsSharedRt()) 114fe6060f1SDimitry Andric Dyld += "hwasan/"; 115e8d8bef9SDimitry Andric if (SanArgs.needsTsanRt() && SanArgs.needsSharedRt()) 116e8d8bef9SDimitry Andric Dyld += "tsan/"; 1170b57cec5SDimitry Andric Dyld += "ld.so.1"; 1180b57cec5SDimitry Andric CmdArgs.push_back("-dynamic-linker"); 1190b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Dyld)); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 122*0fca6ea1SDimitry Andric if (Triple.isRISCV64()) { 12381ad6265SDimitry Andric CmdArgs.push_back("-X"); 124*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_mno_relax)) 125*0fca6ea1SDimitry Andric CmdArgs.push_back("--no-relax"); 126*0fca6ea1SDimitry Andric } 12781ad6265SDimitry Andric 1280b57cec5SDimitry Andric CmdArgs.push_back("-o"); 1290b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 1300b57cec5SDimitry Andric 13104eeddc0SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 13204eeddc0SDimitry Andric options::OPT_r)) { 1330b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_shared)) { 1340b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o"))); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1385f757f3fSDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u}); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric if (D.isUsingLTO()) { 1430b57cec5SDimitry Andric assert(!Inputs.empty() && "Must have at least one input."); 1445f757f3fSDimitry Andric // Find the first filename InputInfo object. 1455f757f3fSDimitry Andric auto Input = llvm::find_if( 1465f757f3fSDimitry Andric Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); }); 1475f757f3fSDimitry Andric if (Input == Inputs.end()) 1485f757f3fSDimitry Andric // For a very rare case, all of the inputs to the linker are 1495f757f3fSDimitry Andric // InputArg. If that happens, just use the first InputInfo. 1505f757f3fSDimitry Andric Input = Inputs.begin(); 1515f757f3fSDimitry Andric 1525f757f3fSDimitry Andric addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input, 1530b57cec5SDimitry Andric D.getLTOMode() == LTOK_Thin); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 15681ad6265SDimitry Andric addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); 1570b57cec5SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 1580b57cec5SDimitry Andric 15904eeddc0SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 16004eeddc0SDimitry Andric options::OPT_r)) { 1610b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 1620b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric if (D.CCCIsCXX()) { 1650b57cec5SDimitry Andric if (ToolChain.ShouldLinkCXXStdlib(Args)) { 1660b57cec5SDimitry Andric bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 1670b57cec5SDimitry Andric !Args.hasArg(options::OPT_static); 1680b57cec5SDimitry Andric CmdArgs.push_back("--push-state"); 1690b57cec5SDimitry Andric CmdArgs.push_back("--as-needed"); 1700b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 1710b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 1720b57cec5SDimitry Andric ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 1730b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 1740b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1750b57cec5SDimitry Andric CmdArgs.push_back("-lm"); 1760b57cec5SDimitry Andric CmdArgs.push_back("--pop-state"); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 18081ad6265SDimitry Andric // Note that Fuchsia never needs to link in sanitizer runtime deps. Any 18181ad6265SDimitry Andric // sanitizer runtimes with system dependencies use the `.deplibs` feature 18281ad6265SDimitry Andric // instead. 18381ad6265SDimitry Andric addSanitizerRuntimes(ToolChain, Args, CmdArgs); 1840b57cec5SDimitry Andric 18581ad6265SDimitry Andric addXRayRuntime(ToolChain, Args, CmdArgs); 18681ad6265SDimitry Andric 18781ad6265SDimitry Andric ToolChain.addProfileRTLibs(Args, CmdArgs); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric AddRunTimeLibs(ToolChain, D, CmdArgs, Args); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread) || 1920b57cec5SDimitry Andric Args.hasArg(options::OPT_pthreads)) 1930b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fsplit_stack)) 1960b57cec5SDimitry Andric CmdArgs.push_back("--wrap=pthread_create"); 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nolibc)) 1990b57cec5SDimitry Andric CmdArgs.push_back("-lc"); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 20206c3fb27SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 20306c3fb27SDimitry Andric ResponseFileSupport::AtFileCurCP(), 20406c3fb27SDimitry Andric Exec, CmdArgs, Inputs, Output)); 20506c3fb27SDimitry Andric } 20606c3fb27SDimitry Andric 20706c3fb27SDimitry Andric void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, 20806c3fb27SDimitry Andric const InputInfo &Output, 20906c3fb27SDimitry Andric const InputInfoList &Inputs, 21006c3fb27SDimitry Andric const ArgList &Args, 21106c3fb27SDimitry Andric const char *LinkingOutput) const { 21206c3fb27SDimitry Andric const Driver &D = getToolChain().getDriver(); 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 21506c3fb27SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 21606c3fb27SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 21706c3fb27SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 21806c3fb27SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 21906c3fb27SDimitry Andric // handled somewhere else. 22006c3fb27SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 22106c3fb27SDimitry Andric // Silence warnings when linking C code with a C++ '-stdlib' argument. 22206c3fb27SDimitry Andric Args.ClaimAllArgs(options::OPT_stdlib_EQ); 22306c3fb27SDimitry Andric 22406c3fb27SDimitry Andric // ar tool command "llvm-ar <options> <output_file> <input_files>". 22506c3fb27SDimitry Andric ArgStringList CmdArgs; 22606c3fb27SDimitry Andric // Create and insert file members with a deterministic index. 22706c3fb27SDimitry Andric CmdArgs.push_back("rcsD"); 22806c3fb27SDimitry Andric CmdArgs.push_back(Output.getFilename()); 22906c3fb27SDimitry Andric 23006c3fb27SDimitry Andric for (const auto &II : Inputs) { 23106c3fb27SDimitry Andric if (II.isFilename()) { 23206c3fb27SDimitry Andric CmdArgs.push_back(II.getFilename()); 23306c3fb27SDimitry Andric } 23406c3fb27SDimitry Andric } 23506c3fb27SDimitry Andric 23606c3fb27SDimitry Andric // Delete old output archive file if it already exists before generating a new 23706c3fb27SDimitry Andric // archive file. 23806c3fb27SDimitry Andric const char *OutputFileName = Output.getFilename(); 23906c3fb27SDimitry Andric if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) { 24006c3fb27SDimitry Andric if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) { 24106c3fb27SDimitry Andric D.Diag(diag::err_drv_unable_to_remove_file) << EC.message(); 24206c3fb27SDimitry Andric return; 24306c3fb27SDimitry Andric } 24406c3fb27SDimitry Andric } 24506c3fb27SDimitry Andric 24606c3fb27SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath()); 24706c3fb27SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 24806c3fb27SDimitry Andric ResponseFileSupport::AtFileCurCP(), 249e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, 2550b57cec5SDimitry Andric const ArgList &Args) 2560b57cec5SDimitry Andric : ToolChain(D, Triple, Args) { 257*0fca6ea1SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric if (!D.SysRoot.empty()) { 2600b57cec5SDimitry Andric SmallString<128> P(D.SysRoot); 2610b57cec5SDimitry Andric llvm::sys::path::append(P, "lib"); 2627a6dacacSDimitry Andric getFilePaths().push_back(std::string(P)); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> { 2660b57cec5SDimitry Andric std::vector<std::string> FP; 2675f757f3fSDimitry Andric if (std::optional<std::string> Path = getStdlibPath()) { 2685f757f3fSDimitry Andric SmallString<128> P(*Path); 2690b57cec5SDimitry Andric llvm::sys::path::append(P, M.gccSuffix()); 2707a6dacacSDimitry Andric FP.push_back(std::string(P)); 27104eeddc0SDimitry Andric } 2720b57cec5SDimitry Andric return FP; 2730b57cec5SDimitry Andric }; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric Multilibs.push_back(Multilib()); 2760b57cec5SDimitry Andric // Use the noexcept variant with -fno-exceptions to avoid the extra overhead. 27706c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("noexcept", {}, {}) 27806c3fb27SDimitry Andric .flag("-fexceptions", /*Disallow=*/true) 27906c3fb27SDimitry Andric .flag("-fno-exceptions") 28006c3fb27SDimitry Andric .makeMultilib()); 2810b57cec5SDimitry Andric // ASan has higher priority because we always want the instrumentated version. 28206c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("asan", {}, {}) 28306c3fb27SDimitry Andric .flag("-fsanitize=address") 28406c3fb27SDimitry Andric .makeMultilib()); 2850b57cec5SDimitry Andric // Use the asan+noexcept variant with ASan and -fno-exceptions. 28606c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("asan+noexcept", {}, {}) 28706c3fb27SDimitry Andric .flag("-fsanitize=address") 28806c3fb27SDimitry Andric .flag("-fexceptions", /*Disallow=*/true) 28906c3fb27SDimitry Andric .flag("-fno-exceptions") 29006c3fb27SDimitry Andric .makeMultilib()); 291fe6060f1SDimitry Andric // HWASan has higher priority because we always want the instrumentated 292fe6060f1SDimitry Andric // version. 29306c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("hwasan", {}, {}) 29406c3fb27SDimitry Andric .flag("-fsanitize=hwaddress") 29506c3fb27SDimitry Andric .makeMultilib()); 296fe6060f1SDimitry Andric // Use the hwasan+noexcept variant with HWASan and -fno-exceptions. 29706c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("hwasan+noexcept", {}, {}) 29806c3fb27SDimitry Andric .flag("-fsanitize=hwaddress") 29906c3fb27SDimitry Andric .flag("-fexceptions", /*Disallow=*/true) 30006c3fb27SDimitry Andric .flag("-fno-exceptions") 30106c3fb27SDimitry Andric .makeMultilib()); 302fe6060f1SDimitry Andric // Use Itanium C++ ABI for the compat multilib. 30306c3fb27SDimitry Andric Multilibs.push_back(MultilibBuilder("compat", {}, {}) 30406c3fb27SDimitry Andric .flag("-fc++-abi=itanium") 30506c3fb27SDimitry Andric .makeMultilib()); 306fe6060f1SDimitry Andric 3070b57cec5SDimitry Andric Multilibs.FilterOut([&](const Multilib &M) { 3080b57cec5SDimitry Andric std::vector<std::string> RD = FilePaths(M); 309349cc55cSDimitry Andric return llvm::all_of(RD, [&](std::string P) { return !getVFS().exists(P); }); 3100b57cec5SDimitry Andric }); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric Multilib::flags_list Flags; 31306c3fb27SDimitry Andric bool Exceptions = 31406c3fb27SDimitry Andric Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true); 31506c3fb27SDimitry Andric addMultilibFlag(Exceptions, "-fexceptions", Flags); 31606c3fb27SDimitry Andric addMultilibFlag(!Exceptions, "-fno-exceptions", Flags); 31706c3fb27SDimitry Andric addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "-fsanitize=address", 318349cc55cSDimitry Andric Flags); 31906c3fb27SDimitry Andric addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(), 32006c3fb27SDimitry Andric "-fsanitize=hwaddress", Flags); 321e8d8bef9SDimitry Andric 322fe6060f1SDimitry Andric addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium", 32306c3fb27SDimitry Andric "-fc++-abi=itanium", Flags); 324e8d8bef9SDimitry Andric 3250b57cec5SDimitry Andric Multilibs.setFilePathsCallback(FilePaths); 3260b57cec5SDimitry Andric 32706c3fb27SDimitry Andric if (Multilibs.select(Flags, SelectedMultilibs)) { 32806c3fb27SDimitry Andric // Ensure that -print-multi-directory only outputs one multilib directory. 32906c3fb27SDimitry Andric Multilib LastSelected = SelectedMultilibs.back(); 33006c3fb27SDimitry Andric SelectedMultilibs = {LastSelected}; 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric if (!SelectedMultilibs.back().isDefault()) 3330b57cec5SDimitry Andric if (const auto &PathsCallback = Multilibs.filePathsCallback()) 33406c3fb27SDimitry Andric for (const auto &Path : PathsCallback(SelectedMultilibs.back())) 3350b57cec5SDimitry Andric // Prepend the multilib path to ensure it takes the precedence. 3360b57cec5SDimitry Andric getFilePaths().insert(getFilePaths().begin(), Path); 3370b57cec5SDimitry Andric } 33806c3fb27SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, 3410b57cec5SDimitry Andric types::ID InputType) const { 3420b57cec5SDimitry Andric llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); 343480093f4SDimitry Andric return Triple.str(); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric Tool *Fuchsia::buildLinker() const { 3470b57cec5SDimitry Andric return new tools::fuchsia::Linker(*this); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 35006c3fb27SDimitry Andric Tool *Fuchsia::buildStaticLibTool() const { 35106c3fb27SDimitry Andric return new tools::fuchsia::StaticLibTool(*this); 35206c3fb27SDimitry Andric } 35306c3fb27SDimitry Andric 3540b57cec5SDimitry Andric ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType( 3550b57cec5SDimitry Andric const ArgList &Args) const { 3560b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { 3570b57cec5SDimitry Andric StringRef Value = A->getValue(); 3580b57cec5SDimitry Andric if (Value != "compiler-rt") 3590b57cec5SDimitry Andric getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name) 3600b57cec5SDimitry Andric << A->getAsString(Args); 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric return ToolChain::RLT_CompilerRT; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric ToolChain::CXXStdlibType 3670b57cec5SDimitry Andric Fuchsia::GetCXXStdlibType(const ArgList &Args) const { 3680b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { 3690b57cec5SDimitry Andric StringRef Value = A->getValue(); 3700b57cec5SDimitry Andric if (Value != "libc++") 3710b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_stdlib_name) 3720b57cec5SDimitry Andric << A->getAsString(Args); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric return ToolChain::CST_Libcxx; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs, 3790b57cec5SDimitry Andric ArgStringList &CC1Args, 3800b57cec5SDimitry Andric Action::OffloadKind) const { 381480093f4SDimitry Andric if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, 3820b57cec5SDimitry Andric options::OPT_fno_use_init_array, true)) 383480093f4SDimitry Andric CC1Args.push_back("-fno-use-init-array"); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 3870b57cec5SDimitry Andric ArgStringList &CC1Args) const { 3880b57cec5SDimitry Andric const Driver &D = getDriver(); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 3910b57cec5SDimitry Andric return; 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 3940b57cec5SDimitry Andric SmallString<128> P(D.ResourceDir); 3950b57cec5SDimitry Andric llvm::sys::path::append(P, "include"); 3960b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 4000b57cec5SDimitry Andric return; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric // Check for configure-time C include directories. 4030b57cec5SDimitry Andric StringRef CIncludeDirs(C_INCLUDE_DIRS); 4040b57cec5SDimitry Andric if (CIncludeDirs != "") { 4050b57cec5SDimitry Andric SmallVector<StringRef, 5> dirs; 4060b57cec5SDimitry Andric CIncludeDirs.split(dirs, ":"); 4070b57cec5SDimitry Andric for (StringRef dir : dirs) { 4080b57cec5SDimitry Andric StringRef Prefix = 4095ffd83dbSDimitry Andric llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot); 4100b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric return; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric if (!D.SysRoot.empty()) { 4160b57cec5SDimitry Andric SmallString<128> P(D.SysRoot); 4170b57cec5SDimitry Andric llvm::sys::path::append(P, "include"); 4180b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, P.str()); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 4230b57cec5SDimitry Andric ArgStringList &CC1Args) const { 424bdd1243dSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, 425bdd1243dSDimitry Andric options::OPT_nostdincxx)) 4260b57cec5SDimitry Andric return; 4270b57cec5SDimitry Andric 428fe6060f1SDimitry Andric const Driver &D = getDriver(); 429fe6060f1SDimitry Andric std::string Target = getTripleString(); 430fe6060f1SDimitry Andric 431fe6060f1SDimitry Andric auto AddCXXIncludePath = [&](StringRef Path) { 432fe6060f1SDimitry Andric std::string Version = detectLibcxxVersion(Path); 433fe6060f1SDimitry Andric if (Version.empty()) 434fe6060f1SDimitry Andric return; 435fe6060f1SDimitry Andric 436*0fca6ea1SDimitry Andric // First add the per-target multilib include dir. 437*0fca6ea1SDimitry Andric if (!SelectedMultilibs.empty() && !SelectedMultilibs.back().isDefault()) { 438*0fca6ea1SDimitry Andric const Multilib &M = SelectedMultilibs.back(); 439*0fca6ea1SDimitry Andric SmallString<128> TargetDir(Path); 440*0fca6ea1SDimitry Andric llvm::sys::path::append(TargetDir, Target, M.gccSuffix(), "c++", Version); 441*0fca6ea1SDimitry Andric if (getVFS().exists(TargetDir)) { 442*0fca6ea1SDimitry Andric addSystemInclude(DriverArgs, CC1Args, TargetDir); 443*0fca6ea1SDimitry Andric } 444*0fca6ea1SDimitry Andric } 445*0fca6ea1SDimitry Andric 446*0fca6ea1SDimitry Andric // Second add the per-target include dir. 447fe6060f1SDimitry Andric SmallString<128> TargetDir(Path); 448fe6060f1SDimitry Andric llvm::sys::path::append(TargetDir, Target, "c++", Version); 449fe6060f1SDimitry Andric if (getVFS().exists(TargetDir)) 450fe6060f1SDimitry Andric addSystemInclude(DriverArgs, CC1Args, TargetDir); 451fe6060f1SDimitry Andric 452*0fca6ea1SDimitry Andric // Third the generic one. 453fe6060f1SDimitry Andric SmallString<128> Dir(Path); 454fe6060f1SDimitry Andric llvm::sys::path::append(Dir, "c++", Version); 455fe6060f1SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Dir); 456fe6060f1SDimitry Andric }; 457fe6060f1SDimitry Andric 4580b57cec5SDimitry Andric switch (GetCXXStdlibType(DriverArgs)) { 4590b57cec5SDimitry Andric case ToolChain::CST_Libcxx: { 460fe6060f1SDimitry Andric SmallString<128> P(D.Dir); 461fe6060f1SDimitry Andric llvm::sys::path::append(P, "..", "include"); 462fe6060f1SDimitry Andric AddCXXIncludePath(P); 4630b57cec5SDimitry Andric break; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric default: 4670b57cec5SDimitry Andric llvm_unreachable("invalid stdlib name"); 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args, 4720b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 4730b57cec5SDimitry Andric switch (GetCXXStdlibType(Args)) { 4740b57cec5SDimitry Andric case ToolChain::CST_Libcxx: 4750b57cec5SDimitry Andric CmdArgs.push_back("-lc++"); 476fcaf7f86SDimitry Andric if (Args.hasArg(options::OPT_fexperimental_library)) 477fcaf7f86SDimitry Andric CmdArgs.push_back("-lc++experimental"); 4780b57cec5SDimitry Andric break; 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 4810b57cec5SDimitry Andric llvm_unreachable("invalid stdlib name"); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric SanitizerMask Fuchsia::getSupportedSanitizers() const { 4860b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 4870b57cec5SDimitry Andric Res |= SanitizerKind::Address; 488fe6060f1SDimitry Andric Res |= SanitizerKind::HWAddress; 4890b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 4900b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 4910b57cec5SDimitry Andric Res |= SanitizerKind::Fuzzer; 4920b57cec5SDimitry Andric Res |= SanitizerKind::FuzzerNoLink; 4935ffd83dbSDimitry Andric Res |= SanitizerKind::Leak; 4940b57cec5SDimitry Andric Res |= SanitizerKind::SafeStack; 4950b57cec5SDimitry Andric Res |= SanitizerKind::Scudo; 496e8d8bef9SDimitry Andric Res |= SanitizerKind::Thread; 4970b57cec5SDimitry Andric return Res; 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric SanitizerMask Fuchsia::getDefaultSanitizers() const { 501480093f4SDimitry Andric SanitizerMask Res; 502480093f4SDimitry Andric switch (getTriple().getArch()) { 503480093f4SDimitry Andric case llvm::Triple::aarch64: 5041ac55f4cSDimitry Andric case llvm::Triple::riscv64: 505480093f4SDimitry Andric Res |= SanitizerKind::ShadowCallStack; 506480093f4SDimitry Andric break; 507480093f4SDimitry Andric case llvm::Triple::x86_64: 508480093f4SDimitry Andric Res |= SanitizerKind::SafeStack; 509480093f4SDimitry Andric break; 510480093f4SDimitry Andric default: 511480093f4SDimitry Andric break; 512480093f4SDimitry Andric } 513480093f4SDimitry Andric return Res; 5140b57cec5SDimitry Andric } 515