brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.5 KiB · 9edfc4d Raw
509 lines · cpp
1//===--- Fuchsia.cpp - Fuchsia ToolChain Implementations --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Fuchsia.h"10#include "clang/Config/config.h"11#include "clang/Driver/CommonArgs.h"12#include "clang/Driver/Compilation.h"13#include "clang/Driver/Driver.h"14#include "clang/Driver/MultilibBuilder.h"15#include "clang/Driver/SanitizerArgs.h"16#include "clang/Options/Options.h"17#include "llvm/Option/ArgList.h"18#include "llvm/Support/FileSystem.h"19#include "llvm/Support/Path.h"20#include "llvm/Support/VirtualFileSystem.h"21 22using namespace clang::driver;23using namespace clang::driver::toolchains;24using namespace clang::driver::tools;25using namespace clang;26using namespace llvm::opt;27 28using tools::addMultilibFlag;29 30void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,31                                   const InputInfo &Output,32                                   const InputInfoList &Inputs,33                                   const ArgList &Args,34                                   const char *LinkingOutput) const {35  const auto &ToolChain = static_cast<const Fuchsia &>(getToolChain());36  const Driver &D = ToolChain.getDriver();37 38  const llvm::Triple &Triple = ToolChain.getEffectiveTriple();39 40  ArgStringList CmdArgs;41 42  // Silence warning for "clang -g foo.o -o foo"43  Args.ClaimAllArgs(options::OPT_g_Group);44  // and "clang -emit-llvm foo.o -o foo"45  Args.ClaimAllArgs(options::OPT_emit_llvm);46  // and for "clang -w foo.o -o foo". Other warning options are already47  // handled somewhere else.48  Args.ClaimAllArgs(options::OPT_w);49 50  CmdArgs.push_back("-z");51  CmdArgs.push_back("max-page-size=4096");52 53  CmdArgs.push_back("-z");54  CmdArgs.push_back("now");55 56  CmdArgs.push_back("-z");57  CmdArgs.push_back("start-stop-visibility=hidden");58 59  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());60  if (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||61      llvm::sys::path::stem(Exec).equals_insensitive("ld.lld")) {62    CmdArgs.push_back("-z");63    CmdArgs.push_back("rodynamic");64    CmdArgs.push_back("-z");65    CmdArgs.push_back("separate-loadable-segments");66    CmdArgs.push_back("-z");67    CmdArgs.push_back("rel");68    CmdArgs.push_back("--pack-dyn-relocs=relr");69  }70 71  if (!D.SysRoot.empty())72    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));73 74  if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))75    CmdArgs.push_back("-pie");76 77  if (Args.hasArg(options::OPT_rdynamic))78    CmdArgs.push_back("-export-dynamic");79 80  if (Args.hasArg(options::OPT_s))81    CmdArgs.push_back("-s");82 83  if (Args.hasArg(options::OPT_r)) {84    CmdArgs.push_back("-r");85  } else {86    CmdArgs.push_back("--build-id");87    CmdArgs.push_back("--hash-style=gnu");88  }89 90  if (ToolChain.getArch() == llvm::Triple::aarch64) {91    CmdArgs.push_back("--execute-only");92 93    std::string CPU = getCPUName(D, Args, Triple);94    if (Args.hasFlag(options::OPT_mfix_cortex_a53_843419,95                     options::OPT_mno_fix_cortex_a53_843419, true) &&96        (CPU.empty() || CPU == "generic" || CPU == "cortex-a53"))97      CmdArgs.push_back("--fix-cortex-a53-843419");98  }99 100  CmdArgs.push_back("--eh-frame-hdr");101 102  if (Args.hasArg(options::OPT_static))103    CmdArgs.push_back("-Bstatic");104  else if (Args.hasArg(options::OPT_shared))105    CmdArgs.push_back("-shared");106 107  const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);108 109  if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) {110    std::string Dyld = D.DyldPrefix;111    if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())112      Dyld += "asan/";113    if (SanArgs.needsHwasanRt() && SanArgs.needsSharedRt())114      Dyld += "hwasan/";115    if (SanArgs.needsTsanRt() && SanArgs.needsSharedRt())116      Dyld += "tsan/";117    Dyld += "ld.so.1";118    CmdArgs.push_back("-dynamic-linker");119    CmdArgs.push_back(Args.MakeArgString(Dyld));120  }121 122  if (Triple.isRISCV64()) {123    CmdArgs.push_back("-X");124    if (Args.hasArg(options::OPT_mno_relax))125      CmdArgs.push_back("--no-relax");126  }127 128  CmdArgs.push_back("-o");129  CmdArgs.push_back(Output.getFilename());130 131  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,132                   options::OPT_r)) {133    if (!Args.hasArg(options::OPT_shared)) {134      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));135    }136  }137 138  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});139 140  ToolChain.AddFilePathLibArgs(Args, CmdArgs);141 142  if (D.isUsingLTO())143    addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs,144                  D.getLTOMode() == LTOK_Thin);145 146  addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);147  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);148 149  // Sample these options first so they are claimed even under -nostdlib et al.150  bool NoLibc = Args.hasArg(options::OPT_nolibc);151  bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&152                             !Args.hasArg(options::OPT_static);153  bool Pthreads = Args.hasArg(options::OPT_pthread, options::OPT_pthreads);154  bool SplitStack = Args.hasArg(options::OPT_fsplit_stack);155  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,156                   options::OPT_r)) {157    if (Args.hasArg(options::OPT_static))158      CmdArgs.push_back("-Bdynamic");159 160    if (D.CCCIsCXX()) {161      if (ToolChain.ShouldLinkCXXStdlib(Args)) {162        CmdArgs.push_back("--push-state");163        CmdArgs.push_back("--as-needed");164        if (OnlyLibstdcxxStatic)165          CmdArgs.push_back("-Bstatic");166        ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);167        if (OnlyLibstdcxxStatic)168          CmdArgs.push_back("-Bdynamic");169        CmdArgs.push_back("-lm");170        CmdArgs.push_back("--pop-state");171      }172    }173 174    // Note that Fuchsia never needs to link in sanitizer runtime deps.  Any175    // sanitizer runtimes with system dependencies use the `.deplibs` feature176    // instead.177    addSanitizerRuntimes(ToolChain, Args, CmdArgs);178 179    addXRayRuntime(ToolChain, Args, CmdArgs);180 181    ToolChain.addProfileRTLibs(Args, CmdArgs);182 183    AddRunTimeLibs(ToolChain, D, CmdArgs, Args);184 185    if (Pthreads)186      CmdArgs.push_back("-lpthread");187 188    if (SplitStack)189      CmdArgs.push_back("--wrap=pthread_create");190 191    if (!NoLibc)192      CmdArgs.push_back("-lc");193  }194 195  C.addCommand(std::make_unique<Command>(JA, *this,196                                         ResponseFileSupport::AtFileCurCP(),197                                         Exec, CmdArgs, Inputs, Output));198}199 200void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,201                                          const InputInfo &Output,202                                          const InputInfoList &Inputs,203                                          const ArgList &Args,204                                          const char *LinkingOutput) const {205  const Driver &D = getToolChain().getDriver();206 207  // Silence warning for "clang -g foo.o -o foo"208  Args.ClaimAllArgs(options::OPT_g_Group);209  // and "clang -emit-llvm foo.o -o foo"210  Args.ClaimAllArgs(options::OPT_emit_llvm);211  // and for "clang -w foo.o -o foo". Other warning options are already212  // handled somewhere else.213  Args.ClaimAllArgs(options::OPT_w);214  // Silence warnings when linking C code with a C++ '-stdlib' argument.215  Args.ClaimAllArgs(options::OPT_stdlib_EQ);216 217  // ar tool command "llvm-ar <options> <output_file> <input_files>".218  ArgStringList CmdArgs;219  // Create and insert file members with a deterministic index.220  CmdArgs.push_back("rcsD");221  CmdArgs.push_back(Output.getFilename());222 223  for (const auto &II : Inputs) {224    if (II.isFilename()) {225      CmdArgs.push_back(II.getFilename());226    }227  }228 229  // Delete old output archive file if it already exists before generating a new230  // archive file.231  const char *OutputFileName = Output.getFilename();232  if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {233    if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {234      D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();235      return;236    }237  }238 239  const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());240  C.addCommand(std::make_unique<Command>(JA, *this,241                                         ResponseFileSupport::AtFileCurCP(),242                                         Exec, CmdArgs, Inputs, Output));243}244 245/// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.246 247Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,248                 const ArgList &Args)249    : ToolChain(D, Triple, Args) {250  getProgramPaths().push_back(getDriver().Dir);251 252  if (!D.SysRoot.empty()) {253    SmallString<128> P(D.SysRoot);254    llvm::sys::path::append(P, "lib");255    getFilePaths().push_back(std::string(P));256  }257 258  auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> {259    std::vector<std::string> FP;260    if (std::optional<std::string> Path = getStdlibPath()) {261      SmallString<128> P(*Path);262      llvm::sys::path::append(P, M.gccSuffix());263      FP.push_back(std::string(P));264    }265    return FP;266  };267 268  Multilibs.push_back(Multilib());269  // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.270  Multilibs.push_back(MultilibBuilder("noexcept", {}, {})271                          .flag("-fexceptions", /*Disallow=*/true)272                          .flag("-fno-exceptions")273                          .makeMultilib());274  // ASan has higher priority because we always want the instrumentated version.275  Multilibs.push_back(MultilibBuilder("asan", {}, {})276                          .flag("-fsanitize=address")277                          .makeMultilib());278  // Use the asan+noexcept variant with ASan and -fno-exceptions.279  Multilibs.push_back(MultilibBuilder("asan+noexcept", {}, {})280                          .flag("-fsanitize=address")281                          .flag("-fexceptions", /*Disallow=*/true)282                          .flag("-fno-exceptions")283                          .makeMultilib());284  // HWASan has higher priority because we always want the instrumentated285  // version.286  Multilibs.push_back(MultilibBuilder("hwasan", {}, {})287                          .flag("-fsanitize=hwaddress")288                          .makeMultilib());289  // Use the hwasan+noexcept variant with HWASan and -fno-exceptions.290  Multilibs.push_back(MultilibBuilder("hwasan+noexcept", {}, {})291                          .flag("-fsanitize=hwaddress")292                          .flag("-fexceptions", /*Disallow=*/true)293                          .flag("-fno-exceptions")294                          .makeMultilib());295  // Use Itanium C++ ABI for the compat multilib.296  Multilibs.push_back(MultilibBuilder("compat", {}, {})297                          .flag("-fc++-abi=itanium")298                          .makeMultilib());299 300  Multilibs.FilterOut([&](const Multilib &M) {301    std::vector<std::string> RD = FilePaths(M);302    return llvm::all_of(RD, [&](std::string P) { return !getVFS().exists(P); });303  });304 305  Multilib::flags_list Flags;306  bool Exceptions =307      Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true);308  addMultilibFlag(Exceptions, "-fexceptions", Flags);309  addMultilibFlag(!Exceptions, "-fno-exceptions", Flags);310  addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "-fsanitize=address",311                  Flags);312  addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(),313                  "-fsanitize=hwaddress", Flags);314 315  addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium",316                  "-fc++-abi=itanium", Flags);317 318  Multilibs.setFilePathsCallback(FilePaths);319 320  if (Multilibs.select(D, Flags, SelectedMultilibs)) {321    // Ensure that -print-multi-directory only outputs one multilib directory.322    Multilib LastSelected = SelectedMultilibs.back();323    SelectedMultilibs = {LastSelected};324 325    if (!SelectedMultilibs.back().isDefault())326      if (const auto &PathsCallback = Multilibs.filePathsCallback())327        for (const auto &Path : PathsCallback(SelectedMultilibs.back()))328          // Prepend the multilib path to ensure it takes the precedence.329          getFilePaths().insert(getFilePaths().begin(), Path);330  }331}332 333std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,334                                                 types::ID InputType) const {335  llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));336  return Triple.str();337}338 339Tool *Fuchsia::buildLinker() const { return new tools::fuchsia::Linker(*this); }340 341Tool *Fuchsia::buildStaticLibTool() const {342  return new tools::fuchsia::StaticLibTool(*this);343}344 345ToolChain::RuntimeLibType346Fuchsia::GetRuntimeLibType(const ArgList &Args) const {347  if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {348    StringRef Value = A->getValue();349    if (Value != "compiler-rt")350      getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)351          << A->getAsString(Args);352  }353 354  return ToolChain::RLT_CompilerRT;355}356 357ToolChain::CXXStdlibType Fuchsia::GetCXXStdlibType(const ArgList &Args) const {358  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {359    StringRef Value = A->getValue();360    if (Value != "libc++")361      getDriver().Diag(diag::err_drv_invalid_stdlib_name)362          << A->getAsString(Args);363  }364 365  return ToolChain::CST_Libcxx;366}367 368void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,369                                    ArgStringList &CC1Args,370                                    Action::OffloadKind) const {371  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,372                          options::OPT_fno_use_init_array, true))373    CC1Args.push_back("-fno-use-init-array");374}375 376void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,377                                        ArgStringList &CC1Args) const {378  const Driver &D = getDriver();379 380  if (DriverArgs.hasArg(options::OPT_nostdinc))381    return;382 383  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {384    SmallString<128> P(D.ResourceDir);385    llvm::sys::path::append(P, "include");386    addSystemInclude(DriverArgs, CC1Args, P);387  }388 389  if (DriverArgs.hasArg(options::OPT_nostdlibinc))390    return;391 392  // Check for configure-time C include directories.393  StringRef CIncludeDirs(C_INCLUDE_DIRS);394  if (CIncludeDirs != "") {395    SmallVector<StringRef, 5> dirs;396    CIncludeDirs.split(dirs, ":");397    for (StringRef dir : dirs) {398      StringRef Prefix =399          llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);400      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);401    }402    return;403  }404 405  if (!D.SysRoot.empty()) {406    SmallString<128> P(D.SysRoot);407    llvm::sys::path::append(P, "include");408    addExternCSystemInclude(DriverArgs, CC1Args, P.str());409  }410}411 412void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,413                                           ArgStringList &CC1Args) const {414  if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,415                        options::OPT_nostdincxx))416    return;417 418  const Driver &D = getDriver();419  std::string Target = getTripleString();420 421  auto AddCXXIncludePath = [&](StringRef Path) {422    std::string Version = detectLibcxxVersion(Path);423    if (Version.empty())424      return;425 426    // First add the per-target multilib include dir.427    if (!SelectedMultilibs.empty() && !SelectedMultilibs.back().isDefault()) {428      const Multilib &M = SelectedMultilibs.back();429      SmallString<128> TargetDir(Path);430      llvm::sys::path::append(TargetDir, Target, M.gccSuffix(), "c++", Version);431      if (getVFS().exists(TargetDir)) {432        addSystemInclude(DriverArgs, CC1Args, TargetDir);433      }434    }435 436    // Second add the per-target include dir.437    SmallString<128> TargetDir(Path);438    llvm::sys::path::append(TargetDir, Target, "c++", Version);439    if (getVFS().exists(TargetDir))440      addSystemInclude(DriverArgs, CC1Args, TargetDir);441 442    // Third the generic one.443    SmallString<128> Dir(Path);444    llvm::sys::path::append(Dir, "c++", Version);445    addSystemInclude(DriverArgs, CC1Args, Dir);446  };447 448  switch (GetCXXStdlibType(DriverArgs)) {449  case ToolChain::CST_Libcxx: {450    SmallString<128> P(D.Dir);451    llvm::sys::path::append(P, "..", "include");452    AddCXXIncludePath(P);453    break;454  }455 456  default:457    llvm_unreachable("invalid stdlib name");458  }459}460 461void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,462                                  ArgStringList &CmdArgs) const {463  switch (GetCXXStdlibType(Args)) {464  case ToolChain::CST_Libcxx:465    CmdArgs.push_back("-lc++");466    if (Args.hasArg(options::OPT_fexperimental_library))467      CmdArgs.push_back("-lc++experimental");468    break;469 470  case ToolChain::CST_Libstdcxx:471    llvm_unreachable("invalid stdlib name");472  }473}474 475SanitizerMask Fuchsia::getSupportedSanitizers() const {476  SanitizerMask Res = ToolChain::getSupportedSanitizers();477  Res |= SanitizerKind::Address;478  Res |= SanitizerKind::HWAddress;479  Res |= SanitizerKind::PointerCompare;480  Res |= SanitizerKind::PointerSubtract;481  Res |= SanitizerKind::Fuzzer;482  Res |= SanitizerKind::FuzzerNoLink;483  Res |= SanitizerKind::Leak;484  Res |= SanitizerKind::Scudo;485  Res |= SanitizerKind::Thread;486  if (getTriple().getArch() == llvm::Triple::x86_64 ||487      getTriple().getArch() == llvm::Triple::x86) {488    Res |= SanitizerKind::SafeStack;489  }490  return Res;491}492 493SanitizerMask Fuchsia::getDefaultSanitizers() const {494  SanitizerMask Res;495  switch (getTriple().getArch()) {496  case llvm::Triple::aarch64:497  case llvm::Triple::riscv64:498    Res |= SanitizerKind::ShadowCallStack;499    break;500  case llvm::Triple::x86:501  case llvm::Triple::x86_64:502    Res |= SanitizerKind::SafeStack;503    break;504  default:505    break;506  }507  return Res;508}509