10b57cec5SDimitry Andric //===-- PPCLinux.cpp - PowerPC ToolChain Implementations --------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "PPCLinux.h" 100b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 1104eeddc0SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 120b57cec5SDimitry Andric #include "clang/Driver/Options.h" 1304eeddc0SDimitry Andric #include "llvm/Support/FileSystem.h" 140b57cec5SDimitry Andric #include "llvm/Support/Path.h" 150b57cec5SDimitry Andric 1604eeddc0SDimitry Andric using namespace clang::driver; 170b57cec5SDimitry Andric using namespace clang::driver::toolchains; 180b57cec5SDimitry Andric using namespace llvm::opt; 1904eeddc0SDimitry Andric using namespace llvm::sys; 2004eeddc0SDimitry Andric 2104eeddc0SDimitry Andric // Glibc older than 2.32 doesn't fully support IEEE float128. Here we check 2204eeddc0SDimitry Andric // glibc version by looking at dynamic linker name. 2304eeddc0SDimitry Andric static bool GlibcSupportsFloat128(const std::string &Linker) { 2404eeddc0SDimitry Andric llvm::SmallVector<char, 16> Path; 2504eeddc0SDimitry Andric 2604eeddc0SDimitry Andric // Resolve potential symlinks to linker. 2704eeddc0SDimitry Andric if (fs::real_path(Linker, Path)) 2804eeddc0SDimitry Andric return false; 2904eeddc0SDimitry Andric llvm::StringRef LinkerName = 3004eeddc0SDimitry Andric path::filename(llvm::StringRef(Path.data(), Path.size())); 3104eeddc0SDimitry Andric 3204eeddc0SDimitry Andric // Since glibc 2.34, the installed .so file is not symlink anymore. But we can 3304eeddc0SDimitry Andric // still safely assume it's newer than 2.32. 34*5f757f3fSDimitry Andric if (LinkerName.starts_with("ld64.so")) 3504eeddc0SDimitry Andric return true; 3604eeddc0SDimitry Andric 37*5f757f3fSDimitry Andric if (!LinkerName.starts_with("ld-2.")) 3804eeddc0SDimitry Andric return false; 3904eeddc0SDimitry Andric unsigned Minor = (LinkerName[5] - '0') * 10 + (LinkerName[6] - '0'); 4004eeddc0SDimitry Andric if (Minor < 32) 4104eeddc0SDimitry Andric return false; 4204eeddc0SDimitry Andric 4304eeddc0SDimitry Andric return true; 4404eeddc0SDimitry Andric } 4504eeddc0SDimitry Andric 4604eeddc0SDimitry Andric PPCLinuxToolChain::PPCLinuxToolChain(const Driver &D, 4704eeddc0SDimitry Andric const llvm::Triple &Triple, 4804eeddc0SDimitry Andric const llvm::opt::ArgList &Args) 4904eeddc0SDimitry Andric : Linux(D, Triple, Args) { 5004eeddc0SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { 5104eeddc0SDimitry Andric StringRef ABIName = A->getValue(); 52bdd1243dSDimitry Andric 53bdd1243dSDimitry Andric if ((ABIName == "ieeelongdouble" && 54bdd1243dSDimitry Andric !SupportIEEEFloat128(D, Triple, Args)) || 55bdd1243dSDimitry Andric (ABIName == "ibmlongdouble" && !supportIBMLongDouble(D, Args))) 5604eeddc0SDimitry Andric D.Diag(diag::warn_drv_unsupported_float_abi_by_lib) << ABIName; 5704eeddc0SDimitry Andric } 5804eeddc0SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 610b57cec5SDimitry Andric ArgStringList &CC1Args) const { 62a7dea167SDimitry Andric if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) && 630b57cec5SDimitry Andric !DriverArgs.hasArg(options::OPT_nobuiltininc)) { 640b57cec5SDimitry Andric const Driver &D = getDriver(); 650b57cec5SDimitry Andric SmallString<128> P(D.ResourceDir); 660b57cec5SDimitry Andric llvm::sys::path::append(P, "include", "ppc_wrappers"); 670b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric Linux::AddClangSystemIncludeArgs(DriverArgs, CC1Args); 710b57cec5SDimitry Andric } 7204eeddc0SDimitry Andric 73bdd1243dSDimitry Andric bool PPCLinuxToolChain::supportIBMLongDouble( 74bdd1243dSDimitry Andric const Driver &D, const llvm::opt::ArgList &Args) const { 75bdd1243dSDimitry Andric if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx)) 76bdd1243dSDimitry Andric return true; 77bdd1243dSDimitry Andric 78bdd1243dSDimitry Andric CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args); 79bdd1243dSDimitry Andric if (StdLib == CST_Libstdcxx) 80bdd1243dSDimitry Andric return true; 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric return StdLib == CST_Libcxx && !defaultToIEEELongDouble(); 83bdd1243dSDimitry Andric } 84bdd1243dSDimitry Andric 8504eeddc0SDimitry Andric bool PPCLinuxToolChain::SupportIEEEFloat128( 8604eeddc0SDimitry Andric const Driver &D, const llvm::Triple &Triple, 8704eeddc0SDimitry Andric const llvm::opt::ArgList &Args) const { 8804eeddc0SDimitry Andric if (!Triple.isLittleEndian() || !Triple.isPPC64()) 8904eeddc0SDimitry Andric return false; 9004eeddc0SDimitry Andric 9104eeddc0SDimitry Andric if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx)) 9204eeddc0SDimitry Andric return true; 9304eeddc0SDimitry Andric 94fb03ea46SDimitry Andric CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args); 9504eeddc0SDimitry Andric bool HasUnsupportedCXXLib = 96bdd1243dSDimitry Andric (StdLib == CST_Libcxx && !defaultToIEEELongDouble()) || 97fb03ea46SDimitry Andric (StdLib == CST_Libstdcxx && 98fb03ea46SDimitry Andric GCCInstallation.getVersion().isOlderThan(12, 1, 0)); 9904eeddc0SDimitry Andric 100bdd1243dSDimitry Andric std::string Linker = Linux::getDynamicLinker(Args); 101bdd1243dSDimitry Andric return GlibcSupportsFloat128((Twine(D.DyldPrefix) + Linker).str()) && 10204eeddc0SDimitry Andric !(D.CCCIsCXX() && HasUnsupportedCXXLib); 10304eeddc0SDimitry Andric } 104