brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.9 KiB · 607eb71 Raw
422 lines · cpp
1//===--- OHOS.cpp - OHOS 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 "OHOS.h"10#include "Arch/ARM.h"11#include "clang/Config/config.h"12#include "clang/Driver/CommonArgs.h"13#include "clang/Driver/Compilation.h"14#include "clang/Driver/Driver.h"15#include "clang/Driver/SanitizerArgs.h"16#include "clang/Options/Options.h"17#include "llvm/Option/ArgList.h"18#include "llvm/ProfileData/InstrProf.h"19#include "llvm/Support/FileSystem.h"20#include "llvm/Support/Path.h"21#include "llvm/Support/VirtualFileSystem.h"22 23using namespace clang::driver;24using namespace clang::driver::toolchains;25using namespace clang::driver::tools;26using namespace clang;27using namespace llvm::opt;28using namespace clang::driver::tools::arm;29 30using tools::addMultilibFlag;31using tools::addPathIfExists;32 33static bool findOHOSMuslMultilibs(const Driver &D,34                                  const Multilib::flags_list &Flags,35                                  DetectedMultilibs &Result) {36  MultilibSet Multilibs;37  Multilibs.push_back(Multilib());38  // -mcpu=cortex-a739  // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard40  // -mfpu=neon-vfpv441  Multilibs.push_back(42      Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));43 44  Multilibs.push_back(45      Multilib("/a7_softfp_neon-vfpv4", {}, {},46               {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));47 48  Multilibs.push_back(49      Multilib("/a7_hard_neon-vfpv4", {}, {},50               {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));51 52  if (Multilibs.select(D, Flags, Result.SelectedMultilibs)) {53    Result.Multilibs = Multilibs;54    return true;55  }56  return false;57}58 59static bool findOHOSMultilibs(const Driver &D,60                                      const ToolChain &TC,61                                      const llvm::Triple &TargetTriple,62                                      StringRef Path, const ArgList &Args,63                                      DetectedMultilibs &Result) {64  Multilib::flags_list Flags;65  bool IsA7 = false;66  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))67    IsA7 = A->getValue() == StringRef("cortex-a7");68  addMultilibFlag(IsA7, "-mcpu=cortex-a7", Flags);69 70  bool IsMFPU = false;71  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))72    IsMFPU = A->getValue() == StringRef("neon-vfpv4");73  addMultilibFlag(IsMFPU, "-mfpu=neon-vfpv4", Flags);74 75  tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args);76  addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft),77                  "-mfloat-abi=soft", Flags);78  addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP),79                  "-mfloat-abi=softfp", Flags);80  addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard),81                  "-mfloat-abi=hard", Flags);82 83  return findOHOSMuslMultilibs(D, Flags, Result);84}85 86std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {87  // For most architectures, just use whatever we have rather than trying to be88  // clever.89  switch (T.getArch()) {90  default:91    break;92 93  // We use the existence of '/lib/<triple>' as a directory to detect some94  // common linux triples that don't quite match the Clang triple for both95  // 32-bit and 64-bit targets. Multiarch fixes its install triples to these96  // regardless of what the actual target triple is.97  case llvm::Triple::arm:98  case llvm::Triple::thumb:99    return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos";100  case llvm::Triple::riscv32:101    return "riscv32-linux-ohos";102  case llvm::Triple::riscv64:103    return "riscv64-linux-ohos";104  case llvm::Triple::mipsel:105    return "mipsel-linux-ohos";106  case llvm::Triple::x86:107    return "i686-linux-ohos";108  case llvm::Triple::x86_64:109    return "x86_64-linux-ohos";110  case llvm::Triple::aarch64:111    return "aarch64-linux-ohos";112  case llvm::Triple::loongarch64:113    return "loongarch64-linux-ohos";114  }115  return T.str();116}117 118std::string OHOS::getMultiarchTriple(const Driver &D,119                                     const llvm::Triple &TargetTriple,120                                     StringRef SysRoot) const {121  return getMultiarchTriple(TargetTriple);122}123 124static std::string makePath(const std::initializer_list<std::string> &IL) {125  SmallString<128> P;126  for (const auto &S : IL)127    llvm::sys::path::append(P, S);128  return static_cast<std::string>(P.str());129}130 131/// OHOS Toolchain132OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)133    : Generic_ELF(D, Triple, Args) {134  std::string SysRoot = computeSysRoot();135 136  // Select the correct multilib according to the given arguments.137  DetectedMultilibs Result;138  findOHOSMultilibs(D, *this, Triple, "", Args, Result);139  Multilibs = Result.Multilibs;140  SelectedMultilibs = Result.SelectedMultilibs;141  if (!SelectedMultilibs.empty()) {142    SelectedMultilib = SelectedMultilibs.back();143  }144 145  getFilePaths().clear();146  for (const auto &CandidateLibPath : getArchSpecificLibPaths())147    if (getVFS().exists(CandidateLibPath))148      getFilePaths().push_back(CandidateLibPath);149 150  getLibraryPaths().clear();151  for (auto &Path : getRuntimePaths())152    if (getVFS().exists(Path))153      getLibraryPaths().push_back(Path);154 155  // OHOS sysroots contain a library directory for each supported OS156  // version as well as some unversioned libraries in the usual multiarch157  // directory. Support --target=aarch64-linux-ohosX.Y.Z or158  // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX159  path_list &Paths = getFilePaths();160  std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"});161  std::string MultiarchTriple = getMultiarchTriple(getTriple());162  addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}),163                  Paths);164  addPathIfExists(D,165                  makePath({D.Dir, "..", "lib", MultiarchTriple,166                            SelectedMultilib.gccSuffix()}),167                  Paths);168 169  addPathIfExists(170      D,171      makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}),172      Paths);173}174 175ToolChain::RuntimeLibType OHOS::GetRuntimeLibType(176    const ArgList &Args) const {177  if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {178    StringRef Value = A->getValue();179    if (Value != "compiler-rt")180      getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)181          << A->getAsString(Args);182  }183 184  return ToolChain::RLT_CompilerRT;185}186 187ToolChain::CXXStdlibType188OHOS::GetCXXStdlibType(const ArgList &Args) const {189  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {190    StringRef Value = A->getValue();191    if (Value != "libc++")192      getDriver().Diag(diag::err_drv_invalid_stdlib_name)193        << A->getAsString(Args);194  }195 196  return ToolChain::CST_Libcxx;197}198 199void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,200                                        ArgStringList &CC1Args) const {201  const Driver &D = getDriver();202  const llvm::Triple &Triple = getTriple();203  std::string SysRoot = computeSysRoot();204 205  if (DriverArgs.hasArg(options::OPT_nostdinc))206    return;207 208  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {209    SmallString<128> P(D.ResourceDir);210    llvm::sys::path::append(P, "include");211    addSystemInclude(DriverArgs, CC1Args, P);212  }213 214  if (DriverArgs.hasArg(options::OPT_nostdlibinc))215    return;216 217  // Check for configure-time C include directories.218  StringRef CIncludeDirs(C_INCLUDE_DIRS);219  if (CIncludeDirs != "") {220    SmallVector<StringRef, 5> dirs;221    CIncludeDirs.split(dirs, ":");222    for (StringRef dir : dirs) {223      StringRef Prefix =224          llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";225      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);226    }227    return;228  }229 230  addExternCSystemInclude(DriverArgs, CC1Args,231                          SysRoot + "/usr/include/" +232                              getMultiarchTriple(Triple));233  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");234  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");235}236 237void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,238                                        ArgStringList &CC1Args) const {239  if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||240      DriverArgs.hasArg(options::OPT_nostdincxx))241    return;242 243  switch (GetCXXStdlibType(DriverArgs)) {244  case ToolChain::CST_Libcxx: {245    std::string IncPath = makePath({getDriver().Dir, "..", "include"});246    std::string IncTargetPath =247        makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"});248    if (getVFS().exists(IncTargetPath)) {249      addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"}));250      addSystemInclude(DriverArgs, CC1Args, IncTargetPath);251    }252    break;253  }254 255  default:256    llvm_unreachable("invalid stdlib name");257  }258}259 260void OHOS::AddCXXStdlibLibArgs(const ArgList &Args,261                                  ArgStringList &CmdArgs) const {262  switch (GetCXXStdlibType(Args)) {263  case ToolChain::CST_Libcxx:264    CmdArgs.push_back("-lc++");265    CmdArgs.push_back("-lc++abi");266    CmdArgs.push_back("-lunwind");267    break;268 269  case ToolChain::CST_Libstdcxx:270    llvm_unreachable("invalid stdlib name");271  }272}273 274std::string OHOS::computeSysRoot() const {275  std::string SysRoot =276      !getDriver().SysRoot.empty()277          ? getDriver().SysRoot278          : makePath({getDriver().Dir, "..", "..", "sysroot"});279  if (!llvm::sys::fs::exists(SysRoot))280    return std::string();281 282  std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())});283  return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot;284}285 286ToolChain::path_list OHOS::getRuntimePaths() const {287  SmallString<128> P;288  path_list Paths;289  const Driver &D = getDriver();290  const llvm::Triple &Triple = getTriple();291 292  // First try the triple passed to driver as --target=<triple>.293  P.assign(D.ResourceDir);294  llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix());295  Paths.push_back(P.c_str());296 297  // Second try the normalized triple.298  P.assign(D.ResourceDir);299  llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix());300  Paths.push_back(P.c_str());301 302  // Third try the effective triple.303  P.assign(D.ResourceDir);304  llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple),305                          SelectedMultilib.gccSuffix());306  Paths.push_back(P.c_str());307 308  return Paths;309}310 311std::string OHOS::getDynamicLinker(const ArgList &Args) const {312  const llvm::Triple &Triple = getTriple();313  const llvm::Triple::ArchType Arch = getArch();314 315  assert(Triple.isMusl());316  std::string ArchName;317  bool IsArm = false;318 319  switch (Arch) {320  case llvm::Triple::arm:321  case llvm::Triple::thumb:322    ArchName = "arm";323    IsArm = true;324    break;325  case llvm::Triple::armeb:326  case llvm::Triple::thumbeb:327    ArchName = "armeb";328    IsArm = true;329    break;330  default:331    ArchName = Triple.getArchName().str();332  }333  if (IsArm &&334      (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))335    ArchName += "hf";336 337  return "/lib/ld-musl-" + ArchName + ".so.1";338}339 340std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component,341                                FileType Type, bool IsFortran) const {342  SmallString<128> Path(getDriver().ResourceDir);343  llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()),344                          SelectedMultilib.gccSuffix());345  const char *Prefix =346      Type == ToolChain::FT_Object ? "" : "lib";347  const char *Suffix;348  switch (Type) {349  case ToolChain::FT_Object:350    Suffix = ".o";351    break;352  case ToolChain::FT_Static:353    Suffix = ".a";354    break;355  case ToolChain::FT_Shared:356    Suffix = ".so";357    break;358  }359  llvm::sys::path::append(360      Path, Prefix + Twine("clang_rt.") + Component + Suffix);361  return static_cast<std::string>(Path.str());362}363 364void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {365  CmdArgs.push_back("-z");366  CmdArgs.push_back("now");367  CmdArgs.push_back("-z");368  CmdArgs.push_back("relro");369  CmdArgs.push_back("-z");370  CmdArgs.push_back(getArch() == llvm::Triple::loongarch64371                        ? "max-page-size=16384"372                        : "max-page-size=4096");373  // .gnu.hash section is not compatible with the MIPS target374  if (getArch() != llvm::Triple::mipsel)375    CmdArgs.push_back("--hash-style=both");376#ifdef ENABLE_LINKER_BUILD_ID377  CmdArgs.push_back("--build-id");378#endif379  CmdArgs.push_back("--enable-new-dtags");380}381 382SanitizerMask OHOS::getSupportedSanitizers() const {383  SanitizerMask Res = ToolChain::getSupportedSanitizers();384  Res |= SanitizerKind::Address;385  Res |= SanitizerKind::PointerCompare;386  Res |= SanitizerKind::PointerSubtract;387  Res |= SanitizerKind::Fuzzer;388  Res |= SanitizerKind::FuzzerNoLink;389  Res |= SanitizerKind::Memory;390  Res |= SanitizerKind::Vptr;391  Res |= SanitizerKind::SafeStack;392  Res |= SanitizerKind::Scudo;393  // TODO: kASAN for liteos ??394  // TODO: Support TSAN and HWASAN and update mask.395  return Res;396}397 398// TODO: Make a base class for Linux and OHOS and move this there.399void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args,400                             llvm::opt::ArgStringList &CmdArgs) const {401  // Add linker option -u__llvm_profile_runtime to cause runtime402  // initialization module to be linked in.403  if (needsProfileRT(Args))404    CmdArgs.push_back(Args.MakeArgString(405        Twine("-u", llvm::getInstrProfRuntimeHookVarName())));406  ToolChain::addProfileRTLibs(Args, CmdArgs);407}408 409ToolChain::path_list OHOS::getArchSpecificLibPaths() const {410  ToolChain::path_list Paths;411  llvm::Triple Triple = getTriple();412  Paths.push_back(413      makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}));414  return Paths;415}416 417ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const {418  if (Args.getLastArg(options::OPT_unwindlib_EQ))419    return Generic_ELF::GetUnwindLibType(Args);420  return GetDefaultUnwindLibType();421}422