brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.6 KiB · 70e66a2 Raw
506 lines · cpp
1//===--- FreeBSD.cpp - FreeBSD 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 "FreeBSD.h"10#include "Arch/ARM.h"11#include "Arch/Mips.h"12#include "Arch/Sparc.h"13#include "clang/Config/config.h"14#include "clang/Driver/CommonArgs.h"15#include "clang/Driver/Compilation.h"16#include "clang/Driver/SanitizerArgs.h"17#include "clang/Options/Options.h"18#include "llvm/Option/ArgList.h"19#include "llvm/Support/VirtualFileSystem.h"20 21using namespace clang::driver;22using namespace clang::driver::tools;23using namespace clang::driver::toolchains;24using namespace clang;25using namespace llvm::opt;26 27void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,28                                      const InputInfo &Output,29                                      const InputInfoList &Inputs,30                                      const ArgList &Args,31                                      const char *LinkingOutput) const {32  const auto &ToolChain = static_cast<const FreeBSD &>(getToolChain());33  const auto &D = getToolChain().getDriver();34  const llvm::Triple &Triple = ToolChain.getTriple();35  ArgStringList CmdArgs;36 37  claimNoWarnArgs(Args);38 39  // When building 32-bit code on FreeBSD/amd64, we have to explicitly40  // instruct as in the base system to assemble 32-bit code.41  switch (ToolChain.getArch()) {42  default:43    break;44  case llvm::Triple::x86:45    CmdArgs.push_back("--32");46    break;47  case llvm::Triple::ppc:48  case llvm::Triple::ppcle:49    CmdArgs.push_back("-a32");50    break;51  case llvm::Triple::mips:52  case llvm::Triple::mipsel:53  case llvm::Triple::mips64:54  case llvm::Triple::mips64el: {55    StringRef CPUName;56    StringRef ABIName;57    mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);58 59    CmdArgs.push_back("-march");60    CmdArgs.push_back(CPUName.data());61 62    CmdArgs.push_back("-mabi");63    CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());64 65    if (Triple.isLittleEndian())66      CmdArgs.push_back("-EL");67    else68      CmdArgs.push_back("-EB");69 70    if (Arg *A = Args.getLastArg(options::OPT_G)) {71      StringRef v = A->getValue();72      CmdArgs.push_back(Args.MakeArgString("-G" + v));73      A->claim();74    }75 76    AddAssemblerKPIC(ToolChain, Args, CmdArgs);77    break;78  }79  case llvm::Triple::arm:80  case llvm::Triple::armeb:81  case llvm::Triple::thumb:82  case llvm::Triple::thumbeb: {83    arm::FloatABI ABI = arm::getARMFloatABI(ToolChain, Args);84 85    if (ABI == arm::FloatABI::Hard)86      CmdArgs.push_back("-mfpu=vfp");87    else88      CmdArgs.push_back("-mfpu=softvfp");89 90    CmdArgs.push_back("-meabi=5");91    break;92  }93  case llvm::Triple::sparcv9: {94    std::string CPU = getCPUName(D, Args, Triple);95    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));96    AddAssemblerKPIC(ToolChain, Args, CmdArgs);97    break;98  }99  }100 101  for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,102                                    options::OPT_fdebug_prefix_map_EQ)) {103    StringRef Map = A->getValue();104    if (!Map.contains('='))105      D.Diag(diag::err_drv_invalid_argument_to_option)106          << Map << A->getOption().getName();107    else {108      CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));109      CmdArgs.push_back(Args.MakeArgString(Map));110    }111    A->claim();112  }113 114  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);115 116  CmdArgs.push_back("-o");117  CmdArgs.push_back(Output.getFilename());118 119  for (const auto &II : Inputs)120    CmdArgs.push_back(II.getFilename());121 122  const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("as"));123  C.addCommand(std::make_unique<Command>(JA, *this,124                                         ResponseFileSupport::AtFileCurCP(),125                                         Exec, CmdArgs, Inputs, Output));126}127 128void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,129                                   const InputInfo &Output,130                                   const InputInfoList &Inputs,131                                   const ArgList &Args,132                                   const char *LinkingOutput) const {133  const auto &ToolChain = static_cast<const FreeBSD &>(getToolChain());134  const Driver &D = ToolChain.getDriver();135  const llvm::Triple &Triple = ToolChain.getTriple();136  const llvm::Triple::ArchType Arch = ToolChain.getArch();137  const bool IsPIE =138      !Args.hasArg(options::OPT_shared) &&139      (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault(Args));140  ArgStringList CmdArgs;141 142  // Silence warning for "clang -g foo.o -o foo"143  Args.ClaimAllArgs(options::OPT_g_Group);144  // and "clang -emit-llvm foo.o -o foo"145  Args.ClaimAllArgs(options::OPT_emit_llvm);146  // and for "clang -w foo.o -o foo". Other warning options are already147  // handled somewhere else.148  Args.ClaimAllArgs(options::OPT_w);149 150  if (!D.SysRoot.empty())151    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));152 153  if (IsPIE)154    CmdArgs.push_back("-pie");155 156  CmdArgs.push_back("--eh-frame-hdr");157  if (Args.hasArg(options::OPT_static)) {158    CmdArgs.push_back("-Bstatic");159  } else {160    if (Args.hasArg(options::OPT_rdynamic))161      CmdArgs.push_back("-export-dynamic");162    if (Args.hasArg(options::OPT_shared)) {163      CmdArgs.push_back("-shared");164    } else if (!Args.hasArg(options::OPT_r)) {165      CmdArgs.push_back("-dynamic-linker");166      CmdArgs.push_back("/libexec/ld-elf.so.1");167    }168    if (Arch == llvm::Triple::arm || Triple.isX86())169      CmdArgs.push_back("--hash-style=both");170    CmdArgs.push_back("--enable-new-dtags");171  }172 173  // Explicitly set the linker emulation for platforms that might not174  // be the default emulation for the linker.175  switch (Arch) {176  case llvm::Triple::x86:177    CmdArgs.push_back("-m");178    CmdArgs.push_back("elf_i386_fbsd");179    break;180  case llvm::Triple::ppc:181    CmdArgs.push_back("-m");182    CmdArgs.push_back("elf32ppc_fbsd");183    break;184  case llvm::Triple::ppcle:185    CmdArgs.push_back("-m");186    // Use generic -- only usage is for freestanding.187    CmdArgs.push_back("elf32lppc");188    break;189  case llvm::Triple::mips:190    CmdArgs.push_back("-m");191    CmdArgs.push_back("elf32btsmip_fbsd");192    break;193  case llvm::Triple::mipsel:194    CmdArgs.push_back("-m");195    CmdArgs.push_back("elf32ltsmip_fbsd");196    break;197  case llvm::Triple::mips64:198    CmdArgs.push_back("-m");199    if (tools::mips::hasMipsAbiArg(Args, "n32"))200      CmdArgs.push_back("elf32btsmipn32_fbsd");201    else202      CmdArgs.push_back("elf64btsmip_fbsd");203    break;204  case llvm::Triple::mips64el:205    CmdArgs.push_back("-m");206    if (tools::mips::hasMipsAbiArg(Args, "n32"))207      CmdArgs.push_back("elf32ltsmipn32_fbsd");208    else209      CmdArgs.push_back("elf64ltsmip_fbsd");210    break;211  case llvm::Triple::riscv64:212    CmdArgs.push_back("-m");213    CmdArgs.push_back("elf64lriscv");214    break;215  case llvm::Triple::loongarch64:216    CmdArgs.push_back("-m");217    CmdArgs.push_back("elf64loongarch");218    break;219  default:220    break;221  }222 223  if (Triple.isLoongArch64() || Triple.isRISCV64()) {224    CmdArgs.push_back("-X");225    if (Args.hasArg(options::OPT_mno_relax))226      CmdArgs.push_back("--no-relax");227  }228 229  if (Arg *A = Args.getLastArg(options::OPT_G)) {230    if (ToolChain.getTriple().isMIPS()) {231      StringRef v = A->getValue();232      CmdArgs.push_back(Args.MakeArgString("-G" + v));233      A->claim();234    }235  }236 237  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");238  if (Output.isFilename()) {239    CmdArgs.push_back("-o");240    CmdArgs.push_back(Output.getFilename());241  }242 243  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,244                   options::OPT_r)) {245    const char *crt1 = nullptr;246    if (!Args.hasArg(options::OPT_shared)) {247      if (Args.hasArg(options::OPT_pg))248        crt1 = "gcrt1.o";249      else if (IsPIE)250        crt1 = "Scrt1.o";251      else252        crt1 = "crt1.o";253    }254    if (crt1)255      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));256 257    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));258 259    const char *crtbegin = nullptr;260    if (Args.hasArg(options::OPT_static))261      crtbegin = "crtbeginT.o";262    else if (Args.hasArg(options::OPT_shared) || IsPIE)263      crtbegin = "crtbeginS.o";264    else265      crtbegin = "crtbegin.o";266 267    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));268  }269 270  Args.AddAllArgs(CmdArgs, options::OPT_L);271  ToolChain.AddFilePathLibArgs(Args, CmdArgs);272  Args.addAllArgs(CmdArgs,273                  {options::OPT_T_Group, options::OPT_s, options::OPT_t});274 275  if (D.isUsingLTO())276    addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs,277                  D.getLTOMode() == LTOK_Thin);278 279  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);280  bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);281  addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);282  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);283 284  unsigned Major = ToolChain.getTriple().getOSMajorVersion();285  bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14;286  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,287                   options::OPT_r)) {288    // Use the static OpenMP runtime with -static-openmp289    bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&290                        !Args.hasArg(options::OPT_static);291    addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);292 293    if (D.CCCIsCXX()) {294      if (ToolChain.ShouldLinkCXXStdlib(Args))295        ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);296      if (Profiling)297        CmdArgs.push_back("-lm_p");298      else299        CmdArgs.push_back("-lm");300    }301 302    // Silence warnings when linking C code with a C++ '-stdlib' argument.303    Args.ClaimAllArgs(options::OPT_stdlib_EQ);304 305    // Additional linker set-up and flags for Fortran. This is required in order306    // to generate executables. As Fortran runtime depends on the C runtime,307    // these dependencies need to be listed before the C runtime below (i.e.308    // AddRunTimeLibs).309    if (D.IsFlangMode() &&310        !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {311      ToolChain.addFortranRuntimeLibraryPath(Args, CmdArgs);312      ToolChain.addFortranRuntimeLibs(Args, CmdArgs);313      if (Profiling)314        CmdArgs.push_back("-lm_p");315      else316        CmdArgs.push_back("-lm");317    }318 319    if (NeedsSanitizerDeps)320      linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);321    if (NeedsXRayDeps)322      linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);323    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding324    // the default system libraries. Just mimic this for now.325    if (Profiling)326      CmdArgs.push_back("-lgcc_p");327    else328      CmdArgs.push_back("-lgcc");329    if (Args.hasArg(options::OPT_static)) {330      CmdArgs.push_back("-lgcc_eh");331    } else if (Profiling) {332      CmdArgs.push_back("-lgcc_eh_p");333    } else {334      CmdArgs.push_back("--as-needed");335      CmdArgs.push_back("-lgcc_s");336      CmdArgs.push_back("--no-as-needed");337    }338 339    if (Args.hasArg(options::OPT_pthread)) {340      if (Profiling)341        CmdArgs.push_back("-lpthread_p");342      else343        CmdArgs.push_back("-lpthread");344    }345 346    if (Profiling) {347      if (Args.hasArg(options::OPT_shared))348        CmdArgs.push_back("-lc");349      else350        CmdArgs.push_back("-lc_p");351      CmdArgs.push_back("-lgcc_p");352    } else {353      CmdArgs.push_back("-lc");354      CmdArgs.push_back("-lgcc");355    }356 357    if (Args.hasArg(options::OPT_static)) {358      CmdArgs.push_back("-lgcc_eh");359    } else if (Profiling) {360      CmdArgs.push_back("-lgcc_eh_p");361    } else {362      CmdArgs.push_back("--as-needed");363      CmdArgs.push_back("-lgcc_s");364      CmdArgs.push_back("--no-as-needed");365    }366  }367 368  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,369                   options::OPT_r)) {370    const char *crtend = nullptr;371    if (Args.hasArg(options::OPT_shared) || IsPIE)372      crtend = "crtendS.o";373    else374      crtend = "crtend.o";375    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));376    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));377  }378 379  ToolChain.addProfileRTLibs(Args, CmdArgs);380 381  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());382  C.addCommand(std::make_unique<Command>(JA, *this,383                                         ResponseFileSupport::AtFileCurCP(),384                                         Exec, CmdArgs, Inputs, Output));385}386 387/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.388 389FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,390                 const ArgList &Args)391    : Generic_ELF(D, Triple, Args) {392 393  // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall394  // back to '/usr/lib' if it doesn't exist.395  if (Triple.isArch32Bit() &&396      D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o")))397    getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32"));398  else399    getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));400}401 402void FreeBSD::AddClangSystemIncludeArgs(403    const llvm::opt::ArgList &DriverArgs,404    llvm::opt::ArgStringList &CC1Args) const {405  const Driver &D = getDriver();406 407  if (DriverArgs.hasArg(options::OPT_nostdinc))408    return;409 410  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {411    SmallString<128> Dir(D.ResourceDir);412    llvm::sys::path::append(Dir, "include");413    addSystemInclude(DriverArgs, CC1Args, Dir.str());414  }415 416  if (DriverArgs.hasArg(options::OPT_nostdlibinc))417    return;418 419  // Check for configure-time C include directories.420  StringRef CIncludeDirs(C_INCLUDE_DIRS);421  if (CIncludeDirs != "") {422    SmallVector<StringRef, 5> dirs;423    CIncludeDirs.split(dirs, ":");424    for (StringRef dir : dirs) {425      StringRef Prefix =426          llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";427      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);428    }429    return;430  }431 432  addExternCSystemInclude(DriverArgs, CC1Args,433                          concat(D.SysRoot, "/usr/include"));434}435 436void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,437                                    llvm::opt::ArgStringList &CC1Args) const {438  addSystemInclude(DriverArgs, CC1Args,439                   concat(getDriver().SysRoot, "/usr/include/c++/v1"));440}441 442void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,443                                  ArgStringList &CmdArgs) const {444  Generic_ELF::AddCXXStdlibLibArgs(Args, CmdArgs);445  unsigned Major = getTriple().getOSMajorVersion();446  bool SuffixedLib = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14;447  if (SuffixedLib && GetCXXStdlibType(Args) == CST_Libcxx)448    std::replace_if(449        CmdArgs.begin(), CmdArgs.end(),450        [](const char *S) { return StringRef(S) == "-lc++"; }, "-lc++_p");451}452 453void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,454                                 ArgStringList &CC1Args) const {455  CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);456}457 458void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs,459                                ArgStringList &CC1Args) const {460  RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);461}462 463Tool *FreeBSD::buildAssembler() const {464  return new tools::freebsd::Assembler(*this);465}466 467Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }468 469bool FreeBSD::HasNativeLLVMSupport() const { return true; }470 471ToolChain::UnwindTableLevel472FreeBSD::getDefaultUnwindTableLevel(const ArgList &Args) const {473  return UnwindTableLevel::Asynchronous;474}475 476bool FreeBSD::isPIEDefault(const llvm::opt::ArgList &Args) const {477  return getSanitizerArgs(Args).requiresPIE();478}479 480SanitizerMask FreeBSD::getSupportedSanitizers() const {481  const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;482  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;483  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;484  const bool IsMIPS64 = getTriple().isMIPS64();485  SanitizerMask Res = ToolChain::getSupportedSanitizers();486  Res |= SanitizerKind::Address;487  Res |= SanitizerKind::PointerCompare;488  Res |= SanitizerKind::PointerSubtract;489  Res |= SanitizerKind::Vptr;490  if (IsAArch64 || IsX86_64 || IsMIPS64) {491    Res |= SanitizerKind::Leak;492    Res |= SanitizerKind::Thread;493  }494  if (IsAArch64 || IsX86 || IsX86_64) {495    Res |= SanitizerKind::SafeStack;496    Res |= SanitizerKind::Fuzzer;497    Res |= SanitizerKind::FuzzerNoLink;498  }499  if (IsAArch64 || IsX86_64) {500    Res |= SanitizerKind::KernelAddress;501    Res |= SanitizerKind::KernelMemory;502    Res |= SanitizerKind::Memory;503  }504  return Res;505}506