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