1 //===-- PPCLinux.cpp - PowerPC ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
16 using namespace clang::driver
;
17 using namespace clang::driver::toolchains
;
18 using namespace llvm::opt
;
19 using namespace llvm::sys
;
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
;
26 // Resolve potential symlinks to linker.
27 if (fs::real_path(Linker
, Path
))
29 llvm::StringRef LinkerName
=
30 path::filename(llvm::StringRef(Path
.data(), Path
.size()));
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("ld64.so"))
37 if (!LinkerName
.starts_with("ld-2."))
39 unsigned Minor
= (LinkerName
[5] - '0') * 10 + (LinkerName
[6] - '0');
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();
53 if ((ABIName
== "ieeelongdouble" &&
54 !SupportIEEEFloat128(D
, Triple
, Args
)) ||
55 (ABIName
== "ibmlongdouble" && !supportIBMLongDouble(D
, Args
)))
56 D
.Diag(diag::warn_drv_unsupported_float_abi_by_lib
) << ABIName
;
60 void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList
&DriverArgs
,
61 ArgStringList
&CC1Args
) const {
62 if (!DriverArgs
.hasArg(clang::driver::options::OPT_nostdinc
) &&
63 !DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
64 const Driver
&D
= getDriver();
65 SmallString
<128> P(D
.ResourceDir
);
66 llvm::sys::path::append(P
, "include", "ppc_wrappers");
67 addSystemInclude(DriverArgs
, CC1Args
, P
);
70 Linux::AddClangSystemIncludeArgs(DriverArgs
, CC1Args
);
73 bool PPCLinuxToolChain::supportIBMLongDouble(
74 const Driver
&D
, const llvm::opt::ArgList
&Args
) const {
75 if (Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostdlibxx
))
78 CXXStdlibType StdLib
= ToolChain::GetCXXStdlibType(Args
);
79 if (StdLib
== CST_Libstdcxx
)
82 return StdLib
== CST_Libcxx
&& !defaultToIEEELongDouble();
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())
91 if (Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostdlibxx
))
94 CXXStdlibType StdLib
= ToolChain::GetCXXStdlibType(Args
);
95 bool HasUnsupportedCXXLib
=
96 (StdLib
== CST_Libcxx
&& !defaultToIEEELongDouble()) ||
97 (StdLib
== CST_Libstdcxx
&&
98 GCCInstallation
.getVersion().isOlderThan(12, 1, 0));
100 std::string Linker
= Linux::getDynamicLinker(Args
);
101 return GlibcSupportsFloat128((Twine(D
.DyldPrefix
) + Linker
).str()) &&
102 !(D
.CCCIsCXX() && HasUnsupportedCXXLib
);