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(path: Linker, output&: Path)) |
28 | return false; |
29 | llvm::StringRef LinkerName = |
30 | path::filename(path: 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.starts_with(Prefix: "ld64.so" )) |
35 | return true; |
36 | |
37 | if (!LinkerName.starts_with(Prefix: "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(Ids: options::OPT_mabi_EQ)) { |
51 | StringRef ABIName = A->getValue(); |
52 | |
53 | if ((ABIName == "ieeelongdouble" && |
54 | !SupportIEEEFloat128(D, Triple, Args)) || |
55 | (ABIName == "ibmlongdouble" && !supportIBMLongDouble(D, Args))) |
56 | D.Diag(DiagID: diag::warn_drv_unsupported_float_abi_by_lib) << ABIName; |
57 | } |
58 | } |
59 | |
60 | void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
61 | ArgStringList &CC1Args) const { |
62 | if (!DriverArgs.hasArg(Ids: clang::driver::options::OPT_nostdinc) && |
63 | !DriverArgs.hasArg(Ids: options::OPT_nobuiltininc)) { |
64 | const Driver &D = getDriver(); |
65 | SmallString<128> P(D.ResourceDir); |
66 | llvm::sys::path::append(path&: P, a: "include" , b: "ppc_wrappers" ); |
67 | addSystemInclude(DriverArgs, CC1Args, Path: P); |
68 | } |
69 | |
70 | Linux::AddClangSystemIncludeArgs(DriverArgs, CC1Args); |
71 | } |
72 | |
73 | bool PPCLinuxToolChain::supportIBMLongDouble( |
74 | const Driver &D, const llvm::opt::ArgList &Args) const { |
75 | if (Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nostdlibxx)) |
76 | return true; |
77 | |
78 | CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args); |
79 | if (StdLib == CST_Libstdcxx) |
80 | return true; |
81 | |
82 | return StdLib == CST_Libcxx && !defaultToIEEELongDouble(); |
83 | } |
84 | |
85 | bool PPCLinuxToolChain::SupportIEEEFloat128( |
86 | const Driver &D, const llvm::Triple &Triple, |
87 | const llvm::opt::ArgList &Args) const { |
88 | if (!Triple.isLittleEndian() || !Triple.isPPC64()) |
89 | return false; |
90 | |
91 | if (Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nostdlibxx)) |
92 | return true; |
93 | |
94 | CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args); |
95 | bool HasUnsupportedCXXLib = |
96 | (StdLib == CST_Libcxx && !defaultToIEEELongDouble()) || |
97 | (StdLib == CST_Libstdcxx && |
98 | GCCInstallation.getVersion().isOlderThan(RHSMajor: 12, RHSMinor: 1, RHSPatch: 0)); |
99 | |
100 | std::string Linker = Linux::getDynamicLinker(Args); |
101 | return GlibcSupportsFloat128(Linker: (Twine(D.DyldPrefix) + Linker).str()) && |
102 | !(D.CCCIsCXX() && HasUnsupportedCXXLib); |
103 | } |
104 | |