xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Fuchsia.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- Fuchsia.cpp - Fuchsia ToolChain Implementations --------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "Fuchsia.h"
107330f729Sjoerg #include "CommonArgs.h"
117330f729Sjoerg #include "clang/Config/config.h"
127330f729Sjoerg #include "clang/Driver/Compilation.h"
137330f729Sjoerg #include "clang/Driver/Driver.h"
147330f729Sjoerg #include "clang/Driver/DriverDiagnostic.h"
157330f729Sjoerg #include "clang/Driver/Options.h"
167330f729Sjoerg #include "clang/Driver/SanitizerArgs.h"
177330f729Sjoerg #include "llvm/Option/ArgList.h"
18*e038c9c4Sjoerg #include "llvm/ProfileData/InstrProf.h"
197330f729Sjoerg #include "llvm/Support/FileSystem.h"
207330f729Sjoerg #include "llvm/Support/Path.h"
217330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
227330f729Sjoerg 
237330f729Sjoerg using namespace clang::driver;
247330f729Sjoerg using namespace clang::driver::toolchains;
257330f729Sjoerg using namespace clang::driver::tools;
267330f729Sjoerg using namespace clang;
277330f729Sjoerg using namespace llvm::opt;
287330f729Sjoerg 
297330f729Sjoerg using tools::addMultilibFlag;
307330f729Sjoerg 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const317330f729Sjoerg void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
327330f729Sjoerg                                    const InputInfo &Output,
337330f729Sjoerg                                    const InputInfoList &Inputs,
347330f729Sjoerg                                    const ArgList &Args,
357330f729Sjoerg                                    const char *LinkingOutput) const {
367330f729Sjoerg   const toolchains::Fuchsia &ToolChain =
377330f729Sjoerg       static_cast<const toolchains::Fuchsia &>(getToolChain());
387330f729Sjoerg   const Driver &D = ToolChain.getDriver();
397330f729Sjoerg 
407330f729Sjoerg   ArgStringList CmdArgs;
417330f729Sjoerg 
427330f729Sjoerg   // Silence warning for "clang -g foo.o -o foo"
437330f729Sjoerg   Args.ClaimAllArgs(options::OPT_g_Group);
447330f729Sjoerg   // and "clang -emit-llvm foo.o -o foo"
457330f729Sjoerg   Args.ClaimAllArgs(options::OPT_emit_llvm);
467330f729Sjoerg   // and for "clang -w foo.o -o foo". Other warning options are already
477330f729Sjoerg   // handled somewhere else.
487330f729Sjoerg   Args.ClaimAllArgs(options::OPT_w);
497330f729Sjoerg 
50*e038c9c4Sjoerg   CmdArgs.push_back("-z");
51*e038c9c4Sjoerg   CmdArgs.push_back("max-page-size=4096");
52*e038c9c4Sjoerg 
53*e038c9c4Sjoerg   CmdArgs.push_back("-z");
54*e038c9c4Sjoerg   CmdArgs.push_back("now");
55*e038c9c4Sjoerg 
567330f729Sjoerg   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
577330f729Sjoerg   if (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
587330f729Sjoerg       llvm::sys::path::stem(Exec).equals_lower("ld.lld")) {
597330f729Sjoerg     CmdArgs.push_back("-z");
607330f729Sjoerg     CmdArgs.push_back("rodynamic");
617330f729Sjoerg     CmdArgs.push_back("-z");
627330f729Sjoerg     CmdArgs.push_back("separate-loadable-segments");
63*e038c9c4Sjoerg     CmdArgs.push_back("--pack-dyn-relocs=relr");
647330f729Sjoerg   }
657330f729Sjoerg 
667330f729Sjoerg   if (!D.SysRoot.empty())
677330f729Sjoerg     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
687330f729Sjoerg 
697330f729Sjoerg   if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))
707330f729Sjoerg     CmdArgs.push_back("-pie");
717330f729Sjoerg 
727330f729Sjoerg   if (Args.hasArg(options::OPT_rdynamic))
737330f729Sjoerg     CmdArgs.push_back("-export-dynamic");
747330f729Sjoerg 
757330f729Sjoerg   if (Args.hasArg(options::OPT_s))
767330f729Sjoerg     CmdArgs.push_back("-s");
777330f729Sjoerg 
787330f729Sjoerg   if (Args.hasArg(options::OPT_r)) {
797330f729Sjoerg     CmdArgs.push_back("-r");
807330f729Sjoerg   } else {
817330f729Sjoerg     CmdArgs.push_back("--build-id");
827330f729Sjoerg     CmdArgs.push_back("--hash-style=gnu");
837330f729Sjoerg   }
847330f729Sjoerg 
857330f729Sjoerg   CmdArgs.push_back("--eh-frame-hdr");
867330f729Sjoerg 
877330f729Sjoerg   if (Args.hasArg(options::OPT_static))
887330f729Sjoerg     CmdArgs.push_back("-Bstatic");
897330f729Sjoerg   else if (Args.hasArg(options::OPT_shared))
907330f729Sjoerg     CmdArgs.push_back("-shared");
917330f729Sjoerg 
927330f729Sjoerg   const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
937330f729Sjoerg 
947330f729Sjoerg   if (!Args.hasArg(options::OPT_shared)) {
957330f729Sjoerg     std::string Dyld = D.DyldPrefix;
967330f729Sjoerg     if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
977330f729Sjoerg       Dyld += "asan/";
98*e038c9c4Sjoerg     if (SanArgs.needsHwasanRt() && SanArgs.needsSharedRt())
99*e038c9c4Sjoerg       Dyld += "hwasan/";
100*e038c9c4Sjoerg     if (SanArgs.needsTsanRt() && SanArgs.needsSharedRt())
101*e038c9c4Sjoerg       Dyld += "tsan/";
1027330f729Sjoerg     Dyld += "ld.so.1";
1037330f729Sjoerg     CmdArgs.push_back("-dynamic-linker");
1047330f729Sjoerg     CmdArgs.push_back(Args.MakeArgString(Dyld));
1057330f729Sjoerg   }
1067330f729Sjoerg 
1077330f729Sjoerg   CmdArgs.push_back("-o");
1087330f729Sjoerg   CmdArgs.push_back(Output.getFilename());
1097330f729Sjoerg 
1107330f729Sjoerg   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
1117330f729Sjoerg     if (!Args.hasArg(options::OPT_shared)) {
1127330f729Sjoerg       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
1137330f729Sjoerg     }
1147330f729Sjoerg   }
1157330f729Sjoerg 
1167330f729Sjoerg   Args.AddAllArgs(CmdArgs, options::OPT_L);
1177330f729Sjoerg   Args.AddAllArgs(CmdArgs, options::OPT_u);
1187330f729Sjoerg 
1197330f729Sjoerg   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
1207330f729Sjoerg 
1217330f729Sjoerg   if (D.isUsingLTO()) {
1227330f729Sjoerg     assert(!Inputs.empty() && "Must have at least one input.");
123*e038c9c4Sjoerg     addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
1247330f729Sjoerg                   D.getLTOMode() == LTOK_Thin);
1257330f729Sjoerg   }
1267330f729Sjoerg 
1277330f729Sjoerg   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
1287330f729Sjoerg   bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
1297330f729Sjoerg   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
1307330f729Sjoerg   ToolChain.addProfileRTLibs(Args, CmdArgs);
1317330f729Sjoerg 
1327330f729Sjoerg   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
1337330f729Sjoerg     if (Args.hasArg(options::OPT_static))
1347330f729Sjoerg       CmdArgs.push_back("-Bdynamic");
1357330f729Sjoerg 
1367330f729Sjoerg     if (D.CCCIsCXX()) {
1377330f729Sjoerg       if (ToolChain.ShouldLinkCXXStdlib(Args)) {
1387330f729Sjoerg         bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
1397330f729Sjoerg                                    !Args.hasArg(options::OPT_static);
1407330f729Sjoerg         CmdArgs.push_back("--push-state");
1417330f729Sjoerg         CmdArgs.push_back("--as-needed");
1427330f729Sjoerg         if (OnlyLibstdcxxStatic)
1437330f729Sjoerg           CmdArgs.push_back("-Bstatic");
1447330f729Sjoerg         ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
1457330f729Sjoerg         if (OnlyLibstdcxxStatic)
1467330f729Sjoerg           CmdArgs.push_back("-Bdynamic");
1477330f729Sjoerg         CmdArgs.push_back("-lm");
1487330f729Sjoerg         CmdArgs.push_back("--pop-state");
1497330f729Sjoerg       }
1507330f729Sjoerg     }
1517330f729Sjoerg 
1527330f729Sjoerg     if (NeedsSanitizerDeps)
1537330f729Sjoerg       linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
1547330f729Sjoerg 
1557330f729Sjoerg     if (NeedsXRayDeps)
1567330f729Sjoerg       linkXRayRuntimeDeps(ToolChain, CmdArgs);
1577330f729Sjoerg 
1587330f729Sjoerg     AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
1597330f729Sjoerg 
1607330f729Sjoerg     if (Args.hasArg(options::OPT_pthread) ||
1617330f729Sjoerg         Args.hasArg(options::OPT_pthreads))
1627330f729Sjoerg       CmdArgs.push_back("-lpthread");
1637330f729Sjoerg 
1647330f729Sjoerg     if (Args.hasArg(options::OPT_fsplit_stack))
1657330f729Sjoerg       CmdArgs.push_back("--wrap=pthread_create");
1667330f729Sjoerg 
1677330f729Sjoerg     if (!Args.hasArg(options::OPT_nolibc))
1687330f729Sjoerg       CmdArgs.push_back("-lc");
1697330f729Sjoerg   }
1707330f729Sjoerg 
171*e038c9c4Sjoerg   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
172*e038c9c4Sjoerg                                          Exec, CmdArgs, Inputs, Output));
1737330f729Sjoerg }
1747330f729Sjoerg 
1757330f729Sjoerg /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.
1767330f729Sjoerg 
Fuchsia(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)1777330f729Sjoerg Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
1787330f729Sjoerg                  const ArgList &Args)
1797330f729Sjoerg     : ToolChain(D, Triple, Args) {
1807330f729Sjoerg   getProgramPaths().push_back(getDriver().getInstalledDir());
1817330f729Sjoerg   if (getDriver().getInstalledDir() != D.Dir)
1827330f729Sjoerg     getProgramPaths().push_back(D.Dir);
1837330f729Sjoerg 
1847330f729Sjoerg   if (!D.SysRoot.empty()) {
1857330f729Sjoerg     SmallString<128> P(D.SysRoot);
1867330f729Sjoerg     llvm::sys::path::append(P, "lib");
187*e038c9c4Sjoerg     getFilePaths().push_back(std::string(P.str()));
1887330f729Sjoerg   }
1897330f729Sjoerg 
1907330f729Sjoerg   auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> {
1917330f729Sjoerg     std::vector<std::string> FP;
192*e038c9c4Sjoerg     SmallString<128> P(getStdlibPath());
1937330f729Sjoerg     llvm::sys::path::append(P, M.gccSuffix());
194*e038c9c4Sjoerg     FP.push_back(std::string(P.str()));
1957330f729Sjoerg     return FP;
1967330f729Sjoerg   };
1977330f729Sjoerg 
1987330f729Sjoerg   Multilibs.push_back(Multilib());
1997330f729Sjoerg   // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
2007330f729Sjoerg   Multilibs.push_back(Multilib("noexcept", {}, {}, 1)
2017330f729Sjoerg                           .flag("-fexceptions")
2027330f729Sjoerg                           .flag("+fno-exceptions"));
2037330f729Sjoerg   // ASan has higher priority because we always want the instrumentated version.
2047330f729Sjoerg   Multilibs.push_back(Multilib("asan", {}, {}, 2)
2057330f729Sjoerg                           .flag("+fsanitize=address"));
2067330f729Sjoerg   // Use the asan+noexcept variant with ASan and -fno-exceptions.
2077330f729Sjoerg   Multilibs.push_back(Multilib("asan+noexcept", {}, {}, 3)
2087330f729Sjoerg                           .flag("+fsanitize=address")
2097330f729Sjoerg                           .flag("-fexceptions")
2107330f729Sjoerg                           .flag("+fno-exceptions"));
211*e038c9c4Sjoerg   // HWASan has higher priority because we always want the instrumentated
212*e038c9c4Sjoerg   // version.
213*e038c9c4Sjoerg   Multilibs.push_back(
214*e038c9c4Sjoerg       Multilib("hwasan", {}, {}, 4).flag("+fsanitize=hwaddress"));
215*e038c9c4Sjoerg   // Use the hwasan+noexcept variant with HWASan and -fno-exceptions.
216*e038c9c4Sjoerg   Multilibs.push_back(Multilib("hwasan+noexcept", {}, {}, 5)
217*e038c9c4Sjoerg                           .flag("+fsanitize=hwaddress")
218*e038c9c4Sjoerg                           .flag("-fexceptions")
219*e038c9c4Sjoerg                           .flag("+fno-exceptions"));
220*e038c9c4Sjoerg   // Use the relative vtables ABI.
221*e038c9c4Sjoerg   // TODO: Remove these multilibs once relative vtables are enabled by default
222*e038c9c4Sjoerg   // for Fuchsia.
223*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables", {}, {}, 6)
224*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables"));
225*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables+noexcept", {}, {}, 7)
226*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables")
227*e038c9c4Sjoerg                           .flag("-fexceptions")
228*e038c9c4Sjoerg                           .flag("+fno-exceptions"));
229*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables+asan", {}, {}, 8)
230*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables")
231*e038c9c4Sjoerg                           .flag("+fsanitize=address"));
232*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables+asan+noexcept", {}, {}, 9)
233*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables")
234*e038c9c4Sjoerg                           .flag("+fsanitize=address")
235*e038c9c4Sjoerg                           .flag("-fexceptions")
236*e038c9c4Sjoerg                           .flag("+fno-exceptions"));
237*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables+hwasan", {}, {}, 10)
238*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables")
239*e038c9c4Sjoerg                           .flag("+fsanitize=hwaddress"));
240*e038c9c4Sjoerg   Multilibs.push_back(Multilib("relative-vtables+hwasan+noexcept", {}, {}, 11)
241*e038c9c4Sjoerg                           .flag("+fexperimental-relative-c++-abi-vtables")
242*e038c9c4Sjoerg                           .flag("+fsanitize=hwaddress")
243*e038c9c4Sjoerg                           .flag("-fexceptions")
244*e038c9c4Sjoerg                           .flag("+fno-exceptions"));
245*e038c9c4Sjoerg   // Use Itanium C++ ABI for the compat multilib.
246*e038c9c4Sjoerg   Multilibs.push_back(Multilib("compat", {}, {}, 12).flag("+fc++-abi=itanium"));
247*e038c9c4Sjoerg 
2487330f729Sjoerg   Multilibs.FilterOut([&](const Multilib &M) {
2497330f729Sjoerg     std::vector<std::string> RD = FilePaths(M);
2507330f729Sjoerg     return std::all_of(RD.begin(), RD.end(), [&](std::string P) {
2517330f729Sjoerg       return !getVFS().exists(P);
2527330f729Sjoerg     });
2537330f729Sjoerg   });
2547330f729Sjoerg 
2557330f729Sjoerg   Multilib::flags_list Flags;
2567330f729Sjoerg   addMultilibFlag(
2577330f729Sjoerg       Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
2587330f729Sjoerg       "fexceptions", Flags);
2597330f729Sjoerg   addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags);
260*e038c9c4Sjoerg   addMultilibFlag(getSanitizerArgs().needsHwasanRt(), "fsanitize=hwaddress",
261*e038c9c4Sjoerg                   Flags);
262*e038c9c4Sjoerg 
263*e038c9c4Sjoerg   addMultilibFlag(
264*e038c9c4Sjoerg       Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
265*e038c9c4Sjoerg                    options::OPT_fno_experimental_relative_cxx_abi_vtables,
266*e038c9c4Sjoerg                    /*default=*/false),
267*e038c9c4Sjoerg       "fexperimental-relative-c++-abi-vtables", Flags);
268*e038c9c4Sjoerg   addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium",
269*e038c9c4Sjoerg                   "fc++-abi=itanium", Flags);
270*e038c9c4Sjoerg 
2717330f729Sjoerg   Multilibs.setFilePathsCallback(FilePaths);
2727330f729Sjoerg 
2737330f729Sjoerg   if (Multilibs.select(Flags, SelectedMultilib))
2747330f729Sjoerg     if (!SelectedMultilib.isDefault())
2757330f729Sjoerg       if (const auto &PathsCallback = Multilibs.filePathsCallback())
2767330f729Sjoerg         for (const auto &Path : PathsCallback(SelectedMultilib))
2777330f729Sjoerg           // Prepend the multilib path to ensure it takes the precedence.
2787330f729Sjoerg           getFilePaths().insert(getFilePaths().begin(), Path);
2797330f729Sjoerg }
2807330f729Sjoerg 
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const2817330f729Sjoerg std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,
2827330f729Sjoerg                                                  types::ID InputType) const {
2837330f729Sjoerg   llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
284*e038c9c4Sjoerg   return Triple.str();
2857330f729Sjoerg }
2867330f729Sjoerg 
buildLinker() const2877330f729Sjoerg Tool *Fuchsia::buildLinker() const {
2887330f729Sjoerg   return new tools::fuchsia::Linker(*this);
2897330f729Sjoerg }
2907330f729Sjoerg 
GetRuntimeLibType(const ArgList & Args) const2917330f729Sjoerg ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType(
2927330f729Sjoerg     const ArgList &Args) const {
2937330f729Sjoerg   if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
2947330f729Sjoerg     StringRef Value = A->getValue();
2957330f729Sjoerg     if (Value != "compiler-rt")
2967330f729Sjoerg       getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)
2977330f729Sjoerg           << A->getAsString(Args);
2987330f729Sjoerg   }
2997330f729Sjoerg 
3007330f729Sjoerg   return ToolChain::RLT_CompilerRT;
3017330f729Sjoerg }
3027330f729Sjoerg 
3037330f729Sjoerg ToolChain::CXXStdlibType
GetCXXStdlibType(const ArgList & Args) const3047330f729Sjoerg Fuchsia::GetCXXStdlibType(const ArgList &Args) const {
3057330f729Sjoerg   if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
3067330f729Sjoerg     StringRef Value = A->getValue();
3077330f729Sjoerg     if (Value != "libc++")
3087330f729Sjoerg       getDriver().Diag(diag::err_drv_invalid_stdlib_name)
3097330f729Sjoerg         << A->getAsString(Args);
3107330f729Sjoerg   }
3117330f729Sjoerg 
3127330f729Sjoerg   return ToolChain::CST_Libcxx;
3137330f729Sjoerg }
3147330f729Sjoerg 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const3157330f729Sjoerg void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,
3167330f729Sjoerg                                     ArgStringList &CC1Args,
3177330f729Sjoerg                                     Action::OffloadKind) const {
318*e038c9c4Sjoerg   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
3197330f729Sjoerg                           options::OPT_fno_use_init_array, true))
320*e038c9c4Sjoerg     CC1Args.push_back("-fno-use-init-array");
3217330f729Sjoerg }
3227330f729Sjoerg 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const3237330f729Sjoerg void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
3247330f729Sjoerg                                         ArgStringList &CC1Args) const {
3257330f729Sjoerg   const Driver &D = getDriver();
3267330f729Sjoerg 
3277330f729Sjoerg   if (DriverArgs.hasArg(options::OPT_nostdinc))
3287330f729Sjoerg     return;
3297330f729Sjoerg 
3307330f729Sjoerg   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
3317330f729Sjoerg     SmallString<128> P(D.ResourceDir);
3327330f729Sjoerg     llvm::sys::path::append(P, "include");
3337330f729Sjoerg     addSystemInclude(DriverArgs, CC1Args, P);
3347330f729Sjoerg   }
3357330f729Sjoerg 
3367330f729Sjoerg   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
3377330f729Sjoerg     return;
3387330f729Sjoerg 
3397330f729Sjoerg   // Check for configure-time C include directories.
3407330f729Sjoerg   StringRef CIncludeDirs(C_INCLUDE_DIRS);
3417330f729Sjoerg   if (CIncludeDirs != "") {
3427330f729Sjoerg     SmallVector<StringRef, 5> dirs;
3437330f729Sjoerg     CIncludeDirs.split(dirs, ":");
3447330f729Sjoerg     for (StringRef dir : dirs) {
3457330f729Sjoerg       StringRef Prefix =
346*e038c9c4Sjoerg           llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
3477330f729Sjoerg       addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
3487330f729Sjoerg     }
3497330f729Sjoerg     return;
3507330f729Sjoerg   }
3517330f729Sjoerg 
3527330f729Sjoerg   if (!D.SysRoot.empty()) {
3537330f729Sjoerg     SmallString<128> P(D.SysRoot);
3547330f729Sjoerg     llvm::sys::path::append(P, "include");
3557330f729Sjoerg     addExternCSystemInclude(DriverArgs, CC1Args, P.str());
3567330f729Sjoerg   }
3577330f729Sjoerg }
3587330f729Sjoerg 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const3597330f729Sjoerg void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
3607330f729Sjoerg                                            ArgStringList &CC1Args) const {
3617330f729Sjoerg   if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
3627330f729Sjoerg       DriverArgs.hasArg(options::OPT_nostdincxx))
3637330f729Sjoerg     return;
3647330f729Sjoerg 
365*e038c9c4Sjoerg   const Driver &D = getDriver();
366*e038c9c4Sjoerg   std::string Target = getTripleString();
367*e038c9c4Sjoerg 
368*e038c9c4Sjoerg   auto AddCXXIncludePath = [&](StringRef Path) {
369*e038c9c4Sjoerg     std::string Version = detectLibcxxVersion(Path);
370*e038c9c4Sjoerg     if (Version.empty())
371*e038c9c4Sjoerg       return;
372*e038c9c4Sjoerg 
373*e038c9c4Sjoerg     // First add the per-target include path.
374*e038c9c4Sjoerg     SmallString<128> TargetDir(Path);
375*e038c9c4Sjoerg     llvm::sys::path::append(TargetDir, Target, "c++", Version);
376*e038c9c4Sjoerg     if (getVFS().exists(TargetDir))
377*e038c9c4Sjoerg       addSystemInclude(DriverArgs, CC1Args, TargetDir);
378*e038c9c4Sjoerg 
379*e038c9c4Sjoerg     // Second add the generic one.
380*e038c9c4Sjoerg     SmallString<128> Dir(Path);
381*e038c9c4Sjoerg     llvm::sys::path::append(Dir, "c++", Version);
382*e038c9c4Sjoerg     addSystemInclude(DriverArgs, CC1Args, Dir);
383*e038c9c4Sjoerg   };
384*e038c9c4Sjoerg 
3857330f729Sjoerg   switch (GetCXXStdlibType(DriverArgs)) {
3867330f729Sjoerg   case ToolChain::CST_Libcxx: {
387*e038c9c4Sjoerg     SmallString<128> P(D.Dir);
388*e038c9c4Sjoerg     llvm::sys::path::append(P, "..", "include");
389*e038c9c4Sjoerg     AddCXXIncludePath(P);
3907330f729Sjoerg     break;
3917330f729Sjoerg   }
3927330f729Sjoerg 
3937330f729Sjoerg   default:
3947330f729Sjoerg     llvm_unreachable("invalid stdlib name");
3957330f729Sjoerg   }
3967330f729Sjoerg }
3977330f729Sjoerg 
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const3987330f729Sjoerg void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
3997330f729Sjoerg                                   ArgStringList &CmdArgs) const {
4007330f729Sjoerg   switch (GetCXXStdlibType(Args)) {
4017330f729Sjoerg   case ToolChain::CST_Libcxx:
4027330f729Sjoerg     CmdArgs.push_back("-lc++");
4037330f729Sjoerg     break;
4047330f729Sjoerg 
4057330f729Sjoerg   case ToolChain::CST_Libstdcxx:
4067330f729Sjoerg     llvm_unreachable("invalid stdlib name");
4077330f729Sjoerg   }
4087330f729Sjoerg }
4097330f729Sjoerg 
getSupportedSanitizers() const4107330f729Sjoerg SanitizerMask Fuchsia::getSupportedSanitizers() const {
4117330f729Sjoerg   SanitizerMask Res = ToolChain::getSupportedSanitizers();
4127330f729Sjoerg   Res |= SanitizerKind::Address;
413*e038c9c4Sjoerg   Res |= SanitizerKind::HWAddress;
4147330f729Sjoerg   Res |= SanitizerKind::PointerCompare;
4157330f729Sjoerg   Res |= SanitizerKind::PointerSubtract;
4167330f729Sjoerg   Res |= SanitizerKind::Fuzzer;
4177330f729Sjoerg   Res |= SanitizerKind::FuzzerNoLink;
418*e038c9c4Sjoerg   Res |= SanitizerKind::Leak;
4197330f729Sjoerg   Res |= SanitizerKind::SafeStack;
4207330f729Sjoerg   Res |= SanitizerKind::Scudo;
421*e038c9c4Sjoerg   Res |= SanitizerKind::Thread;
4227330f729Sjoerg   return Res;
4237330f729Sjoerg }
4247330f729Sjoerg 
getDefaultSanitizers() const4257330f729Sjoerg SanitizerMask Fuchsia::getDefaultSanitizers() const {
4267330f729Sjoerg   SanitizerMask Res;
427*e038c9c4Sjoerg   switch (getTriple().getArch()) {
428*e038c9c4Sjoerg   case llvm::Triple::aarch64:
4297330f729Sjoerg     Res |= SanitizerKind::ShadowCallStack;
430*e038c9c4Sjoerg     break;
431*e038c9c4Sjoerg   case llvm::Triple::x86_64:
4327330f729Sjoerg     Res |= SanitizerKind::SafeStack;
433*e038c9c4Sjoerg     break;
434*e038c9c4Sjoerg   default:
435*e038c9c4Sjoerg     // TODO: Enable SafeStack on RISC-V once tested.
436*e038c9c4Sjoerg     break;
437*e038c9c4Sjoerg   }
4387330f729Sjoerg   return Res;
4397330f729Sjoerg }
440*e038c9c4Sjoerg 
addProfileRTLibs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const441*e038c9c4Sjoerg void Fuchsia::addProfileRTLibs(const llvm::opt::ArgList &Args,
442*e038c9c4Sjoerg                                llvm::opt::ArgStringList &CmdArgs) const {
443*e038c9c4Sjoerg   // Add linker option -u__llvm_profile_runtime to cause runtime
444*e038c9c4Sjoerg   // initialization module to be linked in.
445*e038c9c4Sjoerg   if (needsProfileRT(Args))
446*e038c9c4Sjoerg     CmdArgs.push_back(Args.MakeArgString(
447*e038c9c4Sjoerg         Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
448*e038c9c4Sjoerg   ToolChain::addProfileRTLibs(Args, CmdArgs);
449*e038c9c4Sjoerg }
450