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