PPCLinux.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //===-- PPCLinux.cpp - PowerPC 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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "PPCLinux.h"
  9. #include "clang/Driver/Driver.h"
  10. #include "clang/Driver/DriverDiagnostic.h"
  11. #include "clang/Driver/Options.h"
  12. #include "llvm/Support/FileSystem.h"
  13. #include "llvm/Support/Path.h"
  14. using namespace clang::driver;
  15. using namespace clang::driver::toolchains;
  16. using namespace llvm::opt;
  17. using namespace llvm::sys;
  18. // Glibc older than 2.32 doesn't fully support IEEE float128. Here we check
  19. // glibc version by looking at dynamic linker name.
  20. static bool GlibcSupportsFloat128(const std::string &Linker) {
  21. llvm::SmallVector<char, 16> Path;
  22. // Resolve potential symlinks to linker.
  23. if (fs::real_path(Linker, Path))
  24. return false;
  25. llvm::StringRef LinkerName =
  26. path::filename(llvm::StringRef(Path.data(), Path.size()));
  27. // Since glibc 2.34, the installed .so file is not symlink anymore. But we can
  28. // still safely assume it's newer than 2.32.
  29. if (LinkerName.startswith("ld64.so"))
  30. return true;
  31. if (!LinkerName.startswith("ld-2."))
  32. return false;
  33. unsigned Minor = (LinkerName[5] - '0') * 10 + (LinkerName[6] - '0');
  34. if (Minor < 32)
  35. return false;
  36. return true;
  37. }
  38. PPCLinuxToolChain::PPCLinuxToolChain(const Driver &D,
  39. const llvm::Triple &Triple,
  40. const llvm::opt::ArgList &Args)
  41. : Linux(D, Triple, Args) {
  42. if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
  43. StringRef ABIName = A->getValue();
  44. if ((ABIName == "ieeelongdouble" &&
  45. !SupportIEEEFloat128(D, Triple, Args)) ||
  46. (ABIName == "ibmlongdouble" && !supportIBMLongDouble(D, Args)))
  47. D.Diag(diag::warn_drv_unsupported_float_abi_by_lib) << ABIName;
  48. }
  49. }
  50. void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  51. ArgStringList &CC1Args) const {
  52. if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) &&
  53. !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  54. const Driver &D = getDriver();
  55. SmallString<128> P(D.ResourceDir);
  56. llvm::sys::path::append(P, "include", "ppc_wrappers");
  57. addSystemInclude(DriverArgs, CC1Args, P);
  58. }
  59. Linux::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
  60. }
  61. bool PPCLinuxToolChain::supportIBMLongDouble(
  62. const Driver &D, const llvm::opt::ArgList &Args) const {
  63. if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx))
  64. return true;
  65. CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args);
  66. if (StdLib == CST_Libstdcxx)
  67. return true;
  68. return StdLib == CST_Libcxx && !defaultToIEEELongDouble();
  69. }
  70. bool PPCLinuxToolChain::SupportIEEEFloat128(
  71. const Driver &D, const llvm::Triple &Triple,
  72. const llvm::opt::ArgList &Args) const {
  73. if (!Triple.isLittleEndian() || !Triple.isPPC64())
  74. return false;
  75. if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx))
  76. return true;
  77. CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args);
  78. bool HasUnsupportedCXXLib =
  79. (StdLib == CST_Libcxx && !defaultToIEEELongDouble()) ||
  80. (StdLib == CST_Libstdcxx &&
  81. GCCInstallation.getVersion().isOlderThan(12, 1, 0));
  82. std::string Linker = Linux::getDynamicLinker(Args);
  83. return GlibcSupportsFloat128((Twine(D.DyldPrefix) + Linker).str()) &&
  84. !(D.CCCIsCXX() && HasUnsupportedCXXLib);
  85. }