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