summaryrefslogtreecommitdiff
path: root/Toolchain/Patches
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2021-11-20 16:48:14 +0100
committerBrian Gianforcaro <b.gianfo@gmail.com>2021-11-28 09:38:57 -0800
commitb1f6bfca7fbba32f020f85619826e83901a812c1 (patch)
treec2ed1fe3bc05e71425a64d18f065908ddbab5fd7 /Toolchain/Patches
parentce3b2190211292a704da413501afc9e502c0f148 (diff)
downloadserenity-b1f6bfca7fbba32f020f85619826e83901a812c1.zip
Toolchain/Clang: Support using `libstdc++` as the C++ standard library
This will come in handy if we want to use the LLVM port with a GNU host compiler. As of version 13, libc++ uses `__attribute__((using_if_exists))` to import global LibC functions into the `std` namespace, which allows some symbols to be absent. GCC does not support this attribute, so it fails to build libc++ due to some obscure `wchar.h` functions. This means that cross-compiling libc++ is not possible; and on-target builds would be tedious, so we'll be better off using the toolchain's `libstdc++`.
Diffstat (limited to 'Toolchain/Patches')
-rw-r--r--Toolchain/Patches/llvm.patch60
1 files changed, 53 insertions, 7 deletions
diff --git a/Toolchain/Patches/llvm.patch b/Toolchain/Patches/llvm.patch
index 88f73d824d..2f781da8cc 100644
--- a/Toolchain/Patches/llvm.patch
+++ b/Toolchain/Patches/llvm.patch
@@ -136,10 +136,10 @@ index 58ae08a38..8e9a3fee6 100644
options::OPT_foperator_names, false))
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
new file mode 100644
-index 000000000..461f55ad3
+index 000000000..4d653d86f
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
-@@ -0,0 +1,281 @@
+@@ -0,0 +1,327 @@
+//===---- Serenity.cpp - SerenityOS ToolChain Implementation ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -158,6 +158,7 @@ index 000000000..461f55ad3
+#include "clang/Driver/SanitizerArgs.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
++#include <string>
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
@@ -348,28 +349,73 @@ index 000000000..461f55ad3
+
+ addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include");
+ addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
++}
++
++static std::string getLibStdCXXVersion(const Driver &D, StringRef IncludePath) {
++ SmallString<128> Path(IncludePath);
++ llvm::sys::path::append(Path, "c++");
++
++ std::error_code EC;
++ std::tuple<int, int, int> Newest{0, 0, 0};
++ std::string Result;
++
++ for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
++ !EC && LI != LE; LI = LI.increment(EC)) {
++ StringRef VersionText = llvm::sys::path::filename(LI->path());
++
++ // This is libc++
++ if (VersionText[0] == 'v')
++ continue;
++
++ llvm::SmallVector<StringRef, 3> Parts;
++ VersionText.split(Parts, '.');
++
++ // SerenityOS always builds GCC with <major>.<minor>.<patch> versions
++ if (Parts.size() < 3)
++ continue;
++
++ std::tuple<int, int, int> Current;
++ if (!llvm::to_integer(Parts[0], std::get<0>(Current)))
++ continue;
++ if (!llvm::to_integer(Parts[1], std::get<1>(Current)))
++ continue;
++ if (!llvm::to_integer(Parts[2], std::get<2>(Current)))
++ continue;
++
++ if (Current > Newest) {
++ Newest = Current;
++ Result = VersionText.str();
++ }
+ }
++ return Result;
+}
+
+void Serenity::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
-+ +options::OPT_nostdlibinc))
++ options::OPT_nostdlibinc))
+ return;
+
-+ if (GetCXXStdlibType(DriverArgs) != ToolChain::CST_Libcxx)
-+ llvm_unreachable("Only libc++ is supported on the Serenity target");
++ const auto StdLib = GetCXXStdlibType(DriverArgs);
+
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string Target = getTripleString();
+
+ auto AddIncludePath = [&](std::string Path) {
-+ std::string Version = detectLibcxxVersion(Path);
++ std::string Version = StdLib == CXXStdlibType::CST_Libstdcxx
++ ? getLibStdCXXVersion(D, Path)
++ : detectLibcxxVersion(Path);
+ if (Version.empty())
+ return false;
+
-+ std::string TargetDir = Path + "/" + Target + "/c++/" + Version;
++ std::string TargetDir;
++ if (StdLib == CXXStdlibType::CST_Libstdcxx) {
++ TargetDir = Path + "/c++/" + Version + "/" + Target;
++ } else {
++ TargetDir = Path + "/" + Target + "/c++/" + Version;
++ }
++
+ if (D.getVFS().exists(TargetDir))
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+