[clang] [clang] Add support for SerenityOS (PR #187941)
Lucas Chollet via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 14 02:34:44 PDT 2026
https://github.com/LucasChollet updated https://github.com/llvm/llvm-project/pull/187941
>From 7fddbc845aaae37c7d43430bce4f7d1f4d558d4f Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Sat, 7 Mar 2026 09:36:08 +0100
Subject: [PATCH 01/17] [clang] Add support for SerenityOS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Adds support for the $arch-unknown-serenity target to the Clang front
end. This makes the compiler look for libraries and headers in the right
places, and enables some security mitigations like stack-smashing
protection and position-independent code by default.
Co-authored-by: Daniel Bertalan <dani at danielbertalan.dev>
Co-authored-by: kleines Filmröllchen <filmroellchen at serenityos.org>
Co-authored-by: Andrew Kaster <akaster at serenityos.org>
Co-authored-by: Dan Klishch <danilklishch at gmail.com>
---
clang/lib/Basic/Targets.cpp | 10 +
clang/lib/Basic/Targets/OSTargets.h | 17 ++
clang/lib/Driver/CMakeLists.txt | 1 +
clang/lib/Driver/Driver.cpp | 4 +
clang/lib/Driver/ToolChain.cpp | 5 +-
clang/lib/Driver/ToolChains/Serenity.cpp | 206 ++++++++++++++
clang/lib/Driver/ToolChains/Serenity.h | 90 +++++++
clang/lib/Lex/InitHeaderSearch.cpp | 1 +
.../clang_rt.crtbegin.o | 0
.../clang_rt.crtend.o | 0
.../clang_rt.crtbegin.o | 0
.../clang_rt.crtend.o | 0
.../clang_rt.crtbegin.o | 0
.../x86_64-unknown-serenity/clang_rt.crtend.o | 0
.../serenity_tree/usr/include/c++/v1/.keep | 0
.../Inputs/serenity_tree/usr/lib/crt0.o | 0
.../Inputs/serenity_tree/usr/local/.keep | 0
clang/test/Driver/pic.c | 8 +
clang/test/Driver/save-stats.c | 2 +
clang/test/Driver/serenity.cpp | 254 ++++++++++++++++++
20 files changed, 597 insertions(+), 1 deletion(-)
create mode 100644 clang/lib/Driver/ToolChains/Serenity.cpp
create mode 100644 clang/lib/Driver/ToolChains/Serenity.h
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtbegin.o
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtend.o
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtbegin.o
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtend.o
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtbegin.o
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtend.o
create mode 100644 clang/test/Driver/Inputs/serenity_tree/usr/include/c++/v1/.keep
create mode 100644 clang/test/Driver/Inputs/serenity_tree/usr/lib/crt0.o
create mode 100644 clang/test/Driver/Inputs/serenity_tree/usr/local/.keep
create mode 100644 clang/test/Driver/serenity.cpp
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index dc6ef6ed8f3f8..b24794d26c7c3 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -177,6 +177,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::Hurd:
return std::make_unique<HurdTargetInfo<AArch64leTargetInfo>>(Triple,
Opts);
+ case llvm::Triple::Serenity:
+ return std::make_unique<SerenityTargetInfo<AArch64leTargetInfo>>(Triple,
+ Opts);
case llvm::Triple::Win32:
switch (Triple.getEnvironment()) {
case llvm::Triple::GNU:
@@ -477,6 +480,10 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
Opts);
case llvm::Triple::Hurd:
return std::make_unique<HurdTargetInfo<RISCV64TargetInfo>>(Triple, Opts);
+
+ case llvm::Triple::Serenity:
+ return std::make_unique<SerenityTargetInfo<RISCV64TargetInfo>>(Triple,
+ Opts);
default:
return std::make_unique<RISCV64TargetInfo>(Triple, Opts);
}
@@ -664,6 +671,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::Managarm:
return std::make_unique<ManagarmTargetInfo<X86_64TargetInfo>>(Triple,
Opts);
+ case llvm::Triple::Serenity:
+ return std::make_unique<SerenityTargetInfo<X86_64TargetInfo>>(Triple,
+ Opts);
default:
return std::make_unique<X86_64TargetInfo>(Triple, Opts);
}
diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h
index 16337d56f82c3..9e2916eace079 100644
--- a/clang/lib/Basic/Targets/OSTargets.h
+++ b/clang/lib/Basic/Targets/OSTargets.h
@@ -1104,6 +1104,23 @@ class LLVM_LIBRARY_VISIBILITY QURTTargetInfo : public OSTargetInfo<Target> {
using OSTargetInfo<Target>::OSTargetInfo;
};
+// SerenityOS target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY SerenityTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__serenity__");
+ DefineStd(Builder, "unix", Opts);
+ }
+
+public:
+ SerenityTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WIntType = TargetInfo::UnsignedInt;
+ }
+};
+
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index e3eff21986181..ff8557e8ced97 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -81,6 +81,7 @@ add_clang_library(clangDriver
ToolChains/OHOS.cpp
ToolChains/OpenBSD.cpp
ToolChains/PS4CPU.cpp
+ ToolChains/Serenity.cpp
ToolChains/Solaris.cpp
ToolChains/SPIRV.cpp
ToolChains/SPIRVOpenMP.cpp
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index c559855ac91f5..a57a0e2676052 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -46,6 +46,7 @@
#include "ToolChains/SPIRV.h"
#include "ToolChains/SPIRVOpenMP.h"
#include "ToolChains/SYCL.h"
+#include "ToolChains/Serenity.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/UEFI.h"
@@ -7012,6 +7013,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Managarm:
TC = std::make_unique<toolchains::Managarm>(*this, Target, Args);
break;
+ case llvm::Triple::Serenity:
+ TC = std::make_unique<toolchains::Serenity>(*this, Target, Args);
+ break;
case llvm::Triple::Solaris:
TC = std::make_unique<toolchains::Solaris>(*this, Target, Args);
break;
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 94913837f5339..6c99b4ca837e9 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -724,6 +724,8 @@ StringRef ToolChain::getOSLibName() const {
return "sunos";
case llvm::Triple::AIX:
return "aix";
+ case llvm::Triple::Serenity:
+ return "serenity";
default:
return getOS();
}
@@ -1365,7 +1367,8 @@ ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
else if (LibName == "platform" || LibName == "") {
ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
if (RtLibType == ToolChain::RLT_CompilerRT) {
- if (getTriple().isAndroid() || getTriple().isOSAIX())
+ if (getTriple().isAndroid() || getTriple().isOSAIX() ||
+ getTriple().isOSSerenity())
unwindLibType = ToolChain::UNW_CompilerRT;
else
unwindLibType = ToolChain::UNW_None;
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
new file mode 100644
index 0000000000000..a61f2f81d1f66
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -0,0 +1,206 @@
+//===---- Serenity.cpp - SerenityOS ToolChain Implementation ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Serenity.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Options/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <string>
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const auto &TC = cast<Generic_ELF const&>(getToolChain());
+ const auto &D = TC.getDriver();
+ const bool IsShared = Args.hasArg(options::OPT_shared);
+ const bool IsStatic =
+ Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_static_pie);
+ const bool IsStaticPIE = Args.hasArg(options::OPT_static_pie);
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (IsShared)
+ CmdArgs.push_back("-shared");
+
+ if (IsStaticPIE) {
+ CmdArgs.push_back("-static");
+ CmdArgs.push_back("-pie");
+ CmdArgs.push_back("--no-dynamic-linker");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("text");
+ } else if (IsStatic) {
+ CmdArgs.push_back("-static");
+ } else if (!Args.hasArg(options::OPT_r)) {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ if (!IsShared) {
+ Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
+ options::OPT_nopie);
+ bool IsPIE = A ? A->getOption().matches(options::OPT_pie) :
+ TC.isPIEDefault(Args);
+ if (IsPIE)
+ CmdArgs.push_back("-pie");
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back(Args.MakeArgString(TC.getDynamicLinker(Args)));
+ }
+ }
+
+ CmdArgs.push_back("--eh-frame-hdr");
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("pack-relative-relocs");
+
+ bool HasNoStdLib = Args.hasArg(options::OPT_nostdlib, options::OPT_r);
+ bool HasNoStdLibXX = Args.hasArg(options::OPT_nostdlibxx);
+ bool HasNoLibC = Args.hasArg(options::OPT_nolibc);
+ bool HasNoStartFiles = Args.hasArg(options::OPT_nostartfiles);
+ bool HasNoDefaultLibs = Args.hasArg(options::OPT_nodefaultlibs);
+
+ bool ShouldLinkStartFiles = !HasNoStartFiles && !HasNoStdLib;
+ bool ShouldLinkCompilerRuntime = !HasNoDefaultLibs && !HasNoStdLib;
+ bool ShouldLinkLibC = !HasNoLibC && !HasNoStdLib && !HasNoDefaultLibs;
+ bool ShouldLinkLibCXX =
+ D.CCCIsCXX() && !HasNoStdLibXX && !HasNoStdLib && !HasNoDefaultLibs;
+
+ if (ShouldLinkStartFiles) {
+ if (!IsShared)
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o")));
+
+ std::string crtbegin_path;
+ if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
+ std::string crtbegin =
+ TC.getCompilerRT(Args, "crtbegin", ToolChain::FT_Object);
+ if (TC.getVFS().exists(crtbegin))
+ crtbegin_path = crtbegin;
+ }
+ if (crtbegin_path.empty())
+ crtbegin_path = TC.GetFilePath("crtbeginS.o");
+ CmdArgs.push_back(Args.MakeArgString(crtbegin_path));
+ }
+
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
+
+ TC.AddFilePathLibArgs(Args, CmdArgs);
+
+ if (D.isUsingLTO())
+ addLTOOptions(TC, Args, CmdArgs, Output, Inputs,
+ D.getLTOMode() == LTOK_Thin);
+
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
+
+ addLinkerCompressDebugSectionsOption(TC, Args, CmdArgs);
+
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
+
+ if (ShouldLinkCompilerRuntime) {
+ AddRunTimeLibs(TC, D, CmdArgs, Args);
+
+ // We supply our own sanitizer runtimes that output errors to the
+ // Kernel debug log as well as stderr.
+ // FIXME: Properly port clang/gcc sanitizers and use those instead.
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
+ if (Sanitize.needsUbsanRt())
+ CmdArgs.push_back("-lubsan");
+ }
+
+ if (ShouldLinkLibCXX) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !Args.hasArg(options::OPT_static);
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("--pop-state");
+ }
+
+ // FIXME: This is currently required to building Ports, but we should take
+ // care of that in the Port's build system rather than here.
+ CmdArgs.push_back("-L=/usr/local/lib");
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ if (ShouldLinkLibC)
+ CmdArgs.push_back("-lc");
+
+ if (ShouldLinkStartFiles) {
+ std::string crtend_path;
+ if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
+ std::string crtend =
+ TC.getCompilerRT(Args, "crtend", ToolChain::FT_Object);
+ if (TC.getVFS().exists(crtend))
+ crtend_path = crtend;
+ }
+ if (crtend_path.empty())
+ crtend_path = TC.GetFilePath("crtendS.o");
+ CmdArgs.push_back(Args.MakeArgString(crtend_path));
+ }
+
+ const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
+ C.addCommand(std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::AtFileCurCP(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
+SanitizerMask Serenity::getSupportedSanitizers() const {
+ return ToolChain::getSupportedSanitizers() | SanitizerKind::KernelAddress;
+}
+
+Serenity::Serenity(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
+}
+
+Tool *Serenity::buildLinker() const {
+ return new tools::serenity::Linker(*this);
+}
+
+void Serenity::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc))
+ addSystemInclude(DriverArgs, CC1Args, concat(D.ResourceDir, "/include"));
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // FIXME: See FIXME about "/usr/local/lib" in Linker::ConstructJob.
+ addSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/local/include"));
+
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot, "/usr/include"));
+}
diff --git a/clang/lib/Driver/ToolChains/Serenity.h b/clang/lib/Driver/ToolChains/Serenity.h
new file mode 100644
index 0000000000000..dcf94f016dc6a
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Serenity.h
@@ -0,0 +1,90 @@
+//===---- Serenity.h - SerenityOS ToolChain Implementation ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SERENITY_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SERENITY_H
+
+#include "Gnu.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace serenity {
+
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("serenity::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace serenity
+} // end namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY Serenity final : public Generic_ELF {
+public:
+ Serenity(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+
+ const char *getDefaultLinker() const override { return "ld.lld"; }
+
+ std::string getDynamicLinker(const llvm::opt::ArgList &) const override {
+ return "/usr/lib/Loader.so";
+ }
+
+ bool HasNativeLLVMSupport() const override { return true; }
+
+ bool isPICDefault() const override { return true; }
+ bool isPIEDefault(const llvm::opt::ArgList &) const override { return true; }
+ bool isPICDefaultForced() const override { return false; }
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ bool IsMathErrnoDefault() const override { return false; }
+
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
+ return UnwindTableLevel::Asynchronous;
+ }
+
+ LangOptions::StackProtectorMode
+ GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return LangOptions::SSPStrong;
+ }
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SERENITY_H
diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp
index 3b0e0704ff8c4..e894086b66e76 100644
--- a/clang/lib/Lex/InitHeaderSearch.cpp
+++ b/clang/lib/Lex/InitHeaderSearch.cpp
@@ -227,6 +227,7 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
case llvm::Triple::PS4:
case llvm::Triple::PS5:
case llvm::Triple::RTEMS:
+ case llvm::Triple::Serenity:
case llvm::Triple::Solaris:
case llvm::Triple::UEFI:
case llvm::Triple::WASI:
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtend.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-serenity/clang_rt.crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtend.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/riscv64-unknown-serenity/clang_rt.crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtend.o b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-serenity/clang_rt.crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/serenity_tree/usr/include/c++/v1/.keep b/clang/test/Driver/Inputs/serenity_tree/usr/include/c++/v1/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/serenity_tree/usr/lib/crt0.o b/clang/test/Driver/Inputs/serenity_tree/usr/lib/crt0.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/serenity_tree/usr/local/.keep b/clang/test/Driver/Inputs/serenity_tree/usr/local/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c
index f5d0745422790..7a63e79742f85 100644
--- a/clang/test/Driver/pic.c
+++ b/clang/test/Driver/pic.c
@@ -329,3 +329,11 @@
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
// RUN: %clang -c %s --target=i586-pc-haiku -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
+
+// Serenity has PIC and PIE by default
+// RUN: %clang -c %s --target=x86_64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: %clang -c %s --target=aarch64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: %clang -c %s --target=riscv64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
diff --git a/clang/test/Driver/save-stats.c b/clang/test/Driver/save-stats.c
index ad7867a991686..4821a2f175c32 100644
--- a/clang/test/Driver/save-stats.c
+++ b/clang/test/Driver/save-stats.c
@@ -30,6 +30,8 @@
// RUN: %clang --target=x86_64-unknown-fuchsia -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=x86_64-unknown-haiku -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=x86_64-unknown-haiku -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
+// RUN: %clang --target=x86_64-unknown-serenity -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
+// RUN: %clang --target=x86_64-unknown-serenity -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=avr -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=avr -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// CHECK-LTO: "-stats-file=save-stats.stats"
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
new file mode 100644
index 0000000000000..c748dc0473011
--- /dev/null
+++ b/clang/test/Driver/serenity.cpp
@@ -0,0 +1,254 @@
+// UNSUPPORTED: system-windows
+
+/// Check default header and linker paths for each supported triple
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
+
+// RUN: %clang -### %s --target=aarch64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
+
+// RUN: %clang -### %s --target=riscv64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
+
+// PATHS: "-resource-dir" "[[RESOURCE:[^"]+]]"
+// PATHS-SAME: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
+// PATHS-SAME: "-internal-isystem" "[[RESOURCE]]/include"
+// PATHS-SAME: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// PATHS-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
+// PATHS: "-L[[SYSROOT]]/usr/lib"
+// PATHS-SAME: "-L=/usr/local/lib"
+
+/// Check include paths with -nostdinc
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -fsyntax-only -nostdinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDINC
+// PATH_NOSTDINC: "-nostdsysteminc" "-nobuiltininc"
+// PATH_NOSTDINC-NOT: /include
+
+/// Check include paths with -nobuiltininc
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -fsyntax-only -nobuiltininc 2>&1 | FileCheck %s --check-prefix=PATH_NOBUILTIN
+// PATH_NOBUILTIN: "-nobuiltininc"
+// PATH_NOBUILTIN-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
+// PATH_NOBUILTIN-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+// PATH_NOBUILTIN-NOT: "-internal-isystem" "[[RESOURCE]]/include"
+// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
+
+/// Check include paths with -nostdlibinc
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -fsyntax-only -nostdlibinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDLIBINC
+// PATH_NOSTDLIBINC: "-nostdsysteminc"
+// PATH_NOSTDLIBINC-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
+// PATH_NOSTDLIBINC-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
+// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+// PATH_NOSTDLIBINC-SAME: "-internal-isystem" "[[RESOURCE]]/include"
+// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include"
+
+/// Check default linker args for each supported triple
+// RUN: %clang -### %s --target=x86_64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_X86_64,DEFAULT_LINKER
+// SERENITY_X86_64: "-cc1" "-triple" "[[TRIPLE:x86_64-unknown-serenity]]"
+
+// RUN: %clang -### %s --target=aarch64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_AARCH64,DEFAULT_LINKER
+// SERENITY_AARCH64: "-cc1" "-triple" "[[TRIPLE:aarch64-unknown-serenity]]"
+
+// RUN: %clang -### %s --target=riscv64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_RISCV64,DEFAULT_LINKER
+// SERENITY_RISCV64: "-cc1" "-triple" "[[TRIPLE:riscv64-unknown-serenity]]"
+
+// DEFAULT_LINKER: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// DEFAULT_LINKER-SAME: "-pie"
+// DEFAULT_LINKER-SAME: "-dynamic-linker" "/usr/lib/Loader.so" "--eh-frame-hdr"
+// DEFAULT_LINKER-SAME: "-o" "a.out"
+// DEFAULT_LINKER-SAME: "-z" "pack-relative-relocs"
+// DEFAULT_LINKER-SAME: "crt0.o"
+// DEFAULT_LINKER-SAME: "[[RESOURCE:[^"]+]]/lib/[[TRIPLE]]/clang_rt.crtbegin.o"
+// DEFAULT_LINKER-SAME: "[[RESOURCE]]/lib/[[TRIPLE]]/libclang_rt.builtins.a"
+// DEFAULT_LINKER-SAME: "-lc" "[[RESOURCE]]/lib/[[TRIPLE]]/clang_rt.crtend.o"
+
+/// Check if the sysroot is passed to the linker
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=TestSysroot \
+// RUN: -static-pie 2>&1 | FileCheck %s --check-prefix=LINKER_SYSROOT
+// LINKER_SYSROOT: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// LINKER_SYSROOT-SAME: "--sysroot=TestSysroot"
+
+/// -static-pie suppresses -dynamic-linker
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
+// RUN: -static-pie 2>&1 | FileCheck %s --check-prefix=STATIC_PIE
+// STATIC_PIE: "-static" "-pie"
+// STATIC_PIE-NOT: "-dynamic-linker"
+// STATIC_PIE-SAME: "--no-dynamic-linker" "-z" "text"
+// STATIC_PIE-SAME: "--eh-frame-hdr"
+// STATIC_PIE-SAME: "-z" "pack-relative-relocs"
+// STATIC_PIE-SAME: "crt0.o" "crtbeginS.o"
+// STATIC_PIE-SAME: "-lc" "crtendS.o"
+
+/// -shared forces use of shared crt files
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
+// RUN: -shared 2>&1 | FileCheck %s --check-prefix=SHARED
+// SHARED: "-shared"
+// SHARED-SAME: "--eh-frame-hdr"
+// SHARED-SAME: "-z" "pack-relative-relocs"
+// SHARED-NOT: "crt0.o"
+// SHARED-SAME: "crtbeginS.o"
+// SHARED-SAME: "-lc" "crtendS.o"
+
+/// -static forces use of static crt files
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
+// RUN: -static 2>&1 | FileCheck %s --check-prefix=STATIC
+// STATIC: "-static"
+// STATIC-SAME: "--eh-frame-hdr"
+// STATIC-SAME: "-z" "pack-relative-relocs"
+// STATIC-SAME: "crt0.o" "crtbeginS.o"
+// STATIC-SAME: "-lc" "crtendS.o"
+
+/// -rdynamic passes -export-dynamic
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
+// RUN: -rdynamic 2>&1 | FileCheck %s --check-prefix=RDYNAMIC,RDYNAMIC_SHARED
+// RDYNAMIC: "-export-dynamic" "-pie"
+
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
+// RUN: -no-pie -rdynamic 2>&1 | FileCheck %s --check-prefix=RDYNAMIC_NOPIE,RDYNAMIC_SHARED
+// RDYNAMIC_NOPIE: "-export-dynamic"
+// RDYNAMIC_NOPIE-NOT: "-pie"
+
+// RDYNAMIC_SHARED-SAME: "-dynamic-linker" "/usr/lib/Loader.so" "--eh-frame-hdr"
+// RDYNAMIC_SHARED-SAME: "-o" "a.out"
+// RDYNAMIC_SHARED-SAME: "-z" "pack-relative-relocs"
+// RDYNAMIC_SHARED-SAME: "crt0.o" "crtbeginS.o"
+// RDYNAMIC_SHARED-SAME: "-lc" "crtendS.o"
+
+/// -nostdlib suppresses default -l and crt*.o
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir= \
+// RUN: -nostdlib --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTDLIB
+// NOSTDLIB: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
+// NOSTDLIB-NOT: crt{{[^./]+}}.o
+// NOSTDLIB: "-L
+// NOSTDLIB-SAME: {{^}}[[SYSROOT]]/usr/lib"
+// NOSTDLIB-NOT: "-l
+// NOSTDLIB-NOT: libclang_rt.builtins-x86_64.a
+// NOSTDLIB-NOT: crt{{[^./]+}}.o
+
+// -nostartfiles suppresses crt*.o, but not default -l
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -nostartfiles --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTARTFILES
+// NOSTARTFILES: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
+// NOSTARTFILES-SAME: {{^}}
+// NOSTARTFILES-NOT: crt{{[^./]+}}.o
+// NOSTARTFILES: "-L
+// NOSTARTFILES-SAME: {{^}}[[SYSROOT]]/usr/lib"
+// NOSTARTFILES: lib/x86_64-unknown-serenity/libclang_rt.builtins.a"
+// NOSTARTFILES: "-lc"
+// NOSTARTFILES-NOT: crt{{[^./]+}}.o
+
+/// -r suppresses -dynamic-linker, default -l, and crt*.o like -nostdlib.
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -r --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=RELOCATABLE
+// RELOCATABLE-NOT: "-dynamic-linker"
+// RELOCATABLE: "-internal-isystem"
+// RELOCATABLE-SAME: {{^}} "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
+// RELOCATABLE-NOT: crt{{[^./]+}}.o
+// RELOCATABLE: "-L
+// RELOCATABLE-SAME: {{^}}[[SYSROOT]]/usr/lib"
+// RELOCATABLE-NOT: "-l
+// RELOCATABLE-NOT: crt{{[^./]+}}.o
+// RELOCATABLE-NOT: libclang_rt.builtins-x86_64.a
+
+/// -nolibc suppresses -lc but not other default -l
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -nolibc --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOLIBC
+// NOLIBC: "-internal-isystem"
+// NOLIBC-SAME: {{^}} "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
+// NOLIBC: "[[SYSROOT:[^"]+]]/usr/lib/crt0.o" "crtbeginS.o"
+// NOLIBC: "-L
+// NOLIBC-SAME: {{^}}[[SYSROOT]]/usr/lib"
+// NOLIBC-NOT: "-lc"
+// NOLIBC: "[[RESOURCE:[^"]+]]/lib/x86_64-unknown-serenity/libclang_rt.builtins.a"
+// NOLIBC: "crtendS.o"
+
+/// -fsanitize=undefined redirects to Serenity-custom UBSAN runtime
+// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
+// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -fsanitize=undefined --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=UBSAN
+// UBSAN-NOT: "libclang_rt.ubsan{{[^./]+}}.a"
+// UBSAN-NOT: "libclang_rt.ubsan{{[^./]+}}.so"
+// UBSAN: "-lubsan"
+
+/// C++ stdlib behavior
+// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
+// RUN: 2>&1 | FileCheck %s --check-prefix=DEFAULT_LIBCXX
+// DEFAULT_LIBCXX: "-dynamic-linker" "/usr/lib/Loader.so" "--eh-frame-hdr"
+// DEFAULT_LIBCXX: "-z" "pack-relative-relocs"
+// DEFAULT_LIBCXX: "crt0.o" "crtbeginS.o"
+// DEFAULT_LIBCXX: "--push-state"
+// DEFAULT_LIBCXX: "--as-needed"
+// DEFAULT_LIBCXX: "-lc++"
+// DEFAULT_LIBCXX: "--pop-state"
+// DEFAULT_LIBCXX: "-lc" "crtendS.o"
+
+// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
+// RUN: -static 2>&1 | FileCheck %s --check-prefix=STATIC_LIBCXX
+// STATIC_LIBCXX: "-z" "pack-relative-relocs"
+// STATIC_LIBCXX: "crt0.o" "crtbeginS.o"
+// STATIC_LIBCXX: "--push-state"
+// STATIC_LIBCXX: "--as-needed"
+// STATIC_LIBCXX: "-lc++"
+// STATIC_LIBCXX: "--pop-state"
+// STATIC_LIBCXX: "-lc" "crtendS.o"
+
+// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
+// RUN: -static-libstdc++ 2>&1 | FileCheck %s --check-prefix=STATIC_LIBSTDCXX
+// STATIC_LIBSTDCXX: "-z" "pack-relative-relocs"
+// STATIC_LIBSTDCXX: "crt0.o" "crtbeginS.o"
+// STATIC_LIBSTDCXX: "--push-state"
+// STATIC_LIBSTDCXX: "--as-needed"
+// STATIC_LIBSTDCXX: "-Bstatic"
+// STATIC_LIBSTDCXX: "-lc++"
+// STATIC_LIBSTDCXX: "-Bdynamic"
+// STATIC_LIBSTDCXX: "--pop-state"
+// STATIC_LIBSTDCXX: "-lc" "crtendS.o"
+
+// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
+// RUN: -nostdlib++ 2>&1 | FileCheck %s --check-prefix=NO_LIBCXX
+// NO_LIBCXX: "-z" "pack-relative-relocs"
+// NO_LIBCXX: "crt0.o" "crtbeginS.o"
+// NO_LIBCXX-SAME: "--as-needed"
+// NO_LIBCXX-SAME: "-lunwind"
+// NO_LIBCXX-NOT: "-lc++"
+// NO_LIBCXX-SAME: "-lc" "crtendS.o"
+
+/// Check that unwind tables are enabled
+// RUN: %clang --target=x86_64-unknown-serenity -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// RUN: %clang --target=aarch64-unknown-serenity -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// RUN: %clang --target=riscv64-unknown-serenity -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// UNWIND-TABLES: "-funwind-tables=2"
+
+/// Check that parameters are forwarded to the linker
+
+// RUN: %clang --target=x86_64-unknown-serenity -### %s -L/foo -u bar -T script.ld -s -t -r 2>&1 \
+// RUN: | FileCheck %s --check-prefix=LINK
+// LINK: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// LINK-SAME: "-L/foo"
+// LINK-SAME: "-u" "bar"
+// LINK-SAME: "-T" "script.ld"
+// LINK-SAME: "-s"
+// LINK-SAME: "-t"
+// LINK-SAME: "-r"
+
+// RUN: %clang --target=x86_64-unknown-serenity -### %s -Wl,--compress-debug-sections=zlib 2>&1 \
+// RUN: | FileCheck %s --check-prefix=COMPRESS
+// COMPRESS: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// COMPRESS: "--compress-debug-sections=zlib"
>From 0301cdddae1663ea8092195b9db9e2500f962000 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Sun, 22 Mar 2026 17:23:46 +0100
Subject: [PATCH 02/17] fix ci failures
It surprisingly compiles just fine with GCC.
---
clang/lib/Driver/ToolChains/Serenity.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
index a61f2f81d1f66..c6dbba39b1b39 100644
--- a/clang/lib/Driver/ToolChains/Serenity.cpp
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -27,7 +27,7 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const auto &TC = cast<Generic_ELF const&>(getToolChain());
+ const auto &TC = cast<Generic_ELF>(getToolChain());
const auto &D = TC.getDriver();
const bool IsShared = Args.hasArg(options::OPT_shared);
const bool IsStatic =
@@ -55,8 +55,8 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!IsShared) {
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
options::OPT_nopie);
- bool IsPIE = A ? A->getOption().matches(options::OPT_pie) :
- TC.isPIEDefault(Args);
+ bool IsPIE =
+ A ? A->getOption().matches(options::OPT_pie) : TC.isPIEDefault(Args);
if (IsPIE)
CmdArgs.push_back("-pie");
CmdArgs.push_back("-dynamic-linker");
>From 468b112dfeac0a8a94edd9f6636743f10b31ccda Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Sun, 22 Mar 2026 17:43:42 +0100
Subject: [PATCH 03/17] fix ci failures 2
---
clang/lib/Driver/ToolChains/Serenity.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
index c6dbba39b1b39..a587423873c0d 100644
--- a/clang/lib/Driver/ToolChains/Serenity.cpp
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -27,7 +27,7 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const auto &TC = cast<Generic_ELF>(getToolChain());
+ const auto &TC = static_cast<Generic_ELF const&>(getToolChain());
const auto &D = TC.getDriver();
const bool IsShared = Args.hasArg(options::OPT_shared);
const bool IsStatic =
>From 6d504f9d2c4da41bf8c6396ff084d64d68a2c0ae Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Mon, 23 Mar 2026 08:38:22 +0100
Subject: [PATCH 04/17] make clang-format happy
---
clang/lib/Driver/ToolChains/Serenity.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
index a587423873c0d..3d7467f5d10cb 100644
--- a/clang/lib/Driver/ToolChains/Serenity.cpp
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -27,7 +27,7 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const auto &TC = static_cast<Generic_ELF const&>(getToolChain());
+ const auto &TC = static_cast<Generic_ELF const &>(getToolChain());
const auto &D = TC.getDriver();
const bool IsShared = Args.hasArg(options::OPT_shared);
const bool IsStatic =
>From ba3d9bf7dd9602f5fc21d43e207845496d9d8c57 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 09:49:13 +0200
Subject: [PATCH 05/17] move pic test to serenity.cpp
---
clang/test/Driver/pic.c | 10 +---------
clang/test/Driver/serenity.cpp | 12 ++++++++++++
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c
index 7a63e79742f85..3299e752d87ad 100644
--- a/clang/test/Driver/pic.c
+++ b/clang/test/Driver/pic.c
@@ -328,12 +328,4 @@
// RUN: %clang -c %s --target=x86_64-unknown-haiku -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
// RUN: %clang -c %s --target=i586-pc-haiku -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
-
-// Serenity has PIC and PIE by default
-// RUN: %clang -c %s --target=x86_64-unkown-serenity -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
-// RUN: %clang -c %s --target=aarch64-unkown-serenity -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
-// RUN: %clang -c %s --target=riscv64-unkown-serenity -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
\ No newline at end of file
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index c748dc0473011..7c8af41e8b00b 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -52,6 +52,18 @@
// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include"
+/// Check that PIC and PIE are enabled by default
+// RUN: %clang -c %s --target=x86_64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: %clang -c %s --target=aarch64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+// RUN: %clang -c %s --target=riscv64-unkown-serenity -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
+
+// CHECK-PIE2: "-mrelocation-model" "pic"
+// CHECK-PIE2-SAME: "-pic-level" "2"
+// CHECK-PIE2-SAME: "-pic-is-pie"
+
/// Check default linker args for each supported triple
// RUN: %clang -### %s --target=x86_64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_X86_64,DEFAULT_LINKER
// SERENITY_X86_64: "-cc1" "-triple" "[[TRIPLE:x86_64-unknown-serenity]]"
>From ff1a6c095099d598e1c5d6e8854d6797ea4b586e Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 09:53:27 +0200
Subject: [PATCH 06/17] Indent continuation lines
---
clang/test/Driver/serenity.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 7c8af41e8b00b..a83e033a01a12 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -241,11 +241,11 @@
/// Check that unwind tables are enabled
// RUN: %clang --target=x86_64-unknown-serenity -### -S %s 2>&1 | \
-// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
// RUN: %clang --target=aarch64-unknown-serenity -### -S %s 2>&1 | \
-// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
// RUN: %clang --target=riscv64-unknown-serenity -### -S %s 2>&1 | \
-// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
+// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
// UNWIND-TABLES: "-funwind-tables=2"
/// Check that parameters are forwarded to the linker
>From 9d1bd5ee7686b9bb8ece3ea760dd88e24103a636 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 10:14:59 +0200
Subject: [PATCH 07/17] Remove save-stats and add LTO checks
---
clang/test/Driver/save-stats.c | 2 --
clang/test/Driver/serenity.cpp | 10 ++++++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/clang/test/Driver/save-stats.c b/clang/test/Driver/save-stats.c
index 4821a2f175c32..ad7867a991686 100644
--- a/clang/test/Driver/save-stats.c
+++ b/clang/test/Driver/save-stats.c
@@ -30,8 +30,6 @@
// RUN: %clang --target=x86_64-unknown-fuchsia -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=x86_64-unknown-haiku -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=x86_64-unknown-haiku -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
-// RUN: %clang --target=x86_64-unknown-serenity -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
-// RUN: %clang --target=x86_64-unknown-serenity -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=avr -save-stats -flto -o obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// RUN: %clang --target=avr -save-stats -flto -o obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
// CHECK-LTO: "-stats-file=save-stats.stats"
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index a83e033a01a12..66e30caa2f2f8 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -264,3 +264,13 @@
// RUN: | FileCheck %s --check-prefix=COMPRESS
// COMPRESS: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
// COMPRESS: "--compress-debug-sections=zlib"
+
+/// Check LTO
+// RUN: %clang --target=x86_64-unknown-serenity -flto %s -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=LTO_FULL
+// LTO_FULL: "-plugin-opt=
+// LTO_FULL-NOT: thin
+
+// RUN: %clang --target=x86_64-unknown-serenity -flto=thin %s -### 2>&1 \
+// RUN: | FileCheck %s --check-prefix=LTO_THIN
+// LTO_THIN: "-plugin-opt=thinlto"
\ No newline at end of file
>From ee5925b6d5668e08ac83b978808e6304dcd82f60 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 10:31:16 +0200
Subject: [PATCH 08/17] Add test for __serenity__
---
clang/test/Preprocessor/init-serenityos.c | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 clang/test/Preprocessor/init-serenityos.c
diff --git a/clang/test/Preprocessor/init-serenityos.c b/clang/test/Preprocessor/init-serenityos.c
new file mode 100644
index 0000000000000..e900a6b62ea51
--- /dev/null
+++ b/clang/test/Preprocessor/init-serenityos.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-serenity -E -dM < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix SERENITY %s
+// SERENITY: #define __serenity__ 1
+// SERENITY: #define __unix__ 1
>From 02d03eadad5240e1477e07331451ef21a890220f Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 10:49:29 +0200
Subject: [PATCH 09/17] Remove /usr/local from default paths
---
clang/lib/Driver/ToolChains/Serenity.cpp | 8 --------
clang/test/Driver/serenity.cpp | 6 +-----
2 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp
index 3d7467f5d10cb..7c29b7c932be4 100644
--- a/clang/lib/Driver/ToolChains/Serenity.cpp
+++ b/clang/lib/Driver/ToolChains/Serenity.cpp
@@ -142,10 +142,6 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--pop-state");
}
- // FIXME: This is currently required to building Ports, but we should take
- // care of that in the Port's build system rather than here.
- CmdArgs.push_back("-L=/usr/local/lib");
-
// Silence warnings when linking C code with a C++ '-stdlib' argument.
Args.ClaimAllArgs(options::OPT_stdlib_EQ);
@@ -198,9 +194,5 @@ void Serenity::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- // FIXME: See FIXME about "/usr/local/lib" in Linker::ConstructJob.
- addSystemInclude(DriverArgs, CC1Args,
- concat(D.SysRoot, "/usr/local/include"));
-
addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot, "/usr/include"));
}
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 66e30caa2f2f8..5cb41a10b2252 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -16,10 +16,8 @@
// PATHS: "-resource-dir" "[[RESOURCE:[^"]+]]"
// PATHS-SAME: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
// PATHS-SAME: "-internal-isystem" "[[RESOURCE]]/include"
-// PATHS-SAME: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
// PATHS-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
-// PATHS: "-L[[SYSROOT]]/usr/lib"
-// PATHS-SAME: "-L=/usr/local/lib"
+// PATHS: "-L[[SYSROOT]]/usr/lib"
/// Check include paths with -nostdinc
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
@@ -37,7 +35,6 @@
// PATH_NOBUILTIN-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
// PATH_NOBUILTIN-NOT: "-internal-isystem" "[[RESOURCE]]/include"
-// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
/// Check include paths with -nostdlibinc
@@ -49,7 +46,6 @@
// PATH_NOSTDLIBINC-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
// PATH_NOSTDLIBINC-SAME: "-internal-isystem" "[[RESOURCE]]/include"
-// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include"
/// Check that PIC and PIE are enabled by default
>From bdab28f84f0da2faf88bb3a9d5e491605781615a Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 31 Mar 2026 10:55:51 +0200
Subject: [PATCH 10/17] Add missing empty line at the end of files
---
clang/test/Driver/pic.c | 2 +-
clang/test/Driver/serenity.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c
index 3299e752d87ad..f5d0745422790 100644
--- a/clang/test/Driver/pic.c
+++ b/clang/test/Driver/pic.c
@@ -328,4 +328,4 @@
// RUN: %clang -c %s --target=x86_64-unknown-haiku -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
// RUN: %clang -c %s --target=i586-pc-haiku -### 2>&1 \
-// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
\ No newline at end of file
+// RUN: | FileCheck %s --check-prefix=CHECK-PIC2
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 5cb41a10b2252..8d98c42275776 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -269,4 +269,4 @@
// RUN: %clang --target=x86_64-unknown-serenity -flto=thin %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=LTO_THIN
-// LTO_THIN: "-plugin-opt=thinlto"
\ No newline at end of file
+// LTO_THIN: "-plugin-opt=thinlto"
>From 552ffb26decdf1cfa7beca9bbbf1bb60cbd80f73 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 10:25:48 +0200
Subject: [PATCH 11/17] Remove isPICDefaultForced
---
clang/lib/Driver/ToolChains/Serenity.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChains/Serenity.h b/clang/lib/Driver/ToolChains/Serenity.h
index dcf94f016dc6a..fb77dd6a6eef2 100644
--- a/clang/lib/Driver/ToolChains/Serenity.h
+++ b/clang/lib/Driver/ToolChains/Serenity.h
@@ -63,7 +63,6 @@ class LLVM_LIBRARY_VISIBILITY Serenity final : public Generic_ELF {
bool isPICDefault() const override { return true; }
bool isPIEDefault(const llvm::opt::ArgList &) const override { return true; }
- bool isPICDefaultForced() const override { return false; }
SanitizerMask getSupportedSanitizers() const override;
>From 86afb2f095f1052ac0846bc304a72049391cfd5c Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 10:40:30 +0200
Subject: [PATCH 12/17] Match against generic rt.builtins in tests
---
clang/test/Driver/serenity.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 8d98c42275776..3c32166855345 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -141,7 +141,7 @@
// NOSTDLIB: "-L
// NOSTDLIB-SAME: {{^}}[[SYSROOT]]/usr/lib"
// NOSTDLIB-NOT: "-l
-// NOSTDLIB-NOT: libclang_rt.builtins-x86_64.a
+// NOSTDLIB-NOT: libclang_rt.builtins
// NOSTDLIB-NOT: crt{{[^./]+}}.o
// -nostartfiles suppresses crt*.o, but not default -l
@@ -169,7 +169,7 @@
// RELOCATABLE-SAME: {{^}}[[SYSROOT]]/usr/lib"
// RELOCATABLE-NOT: "-l
// RELOCATABLE-NOT: crt{{[^./]+}}.o
-// RELOCATABLE-NOT: libclang_rt.builtins-x86_64.a
+// RELOCATABLE-NOT: libclang_rt.builtins
/// -nolibc suppresses -lc but not other default -l
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
@@ -188,8 +188,7 @@
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsanitize=undefined --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=UBSAN
-// UBSAN-NOT: "libclang_rt.ubsan{{[^./]+}}.a"
-// UBSAN-NOT: "libclang_rt.ubsan{{[^./]+}}.so"
+// UBSAN-NOT: "libclang_rt.ubsan"
// UBSAN: "-lubsan"
/// C++ stdlib behavior
>From 997e3230c3cbd55ce14dedd902bece080f695ecd Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 10:45:25 +0200
Subject: [PATCH 13/17] Fixup comments: use /// and end sentences with a period
---
clang/test/Driver/serenity.cpp | 39 +++++++++++++++++-----------------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 3c32166855345..e578269976c01 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -1,6 +1,6 @@
// UNSUPPORTED: system-windows
-/// Check default header and linker paths for each supported triple
+/// Check default header and linker paths for each supported triple.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
@@ -19,14 +19,14 @@
// PATHS-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
// PATHS: "-L[[SYSROOT]]/usr/lib"
-/// Check include paths with -nostdinc
+/// Check include paths with -nostdinc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nostdinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDINC
// PATH_NOSTDINC: "-nostdsysteminc" "-nobuiltininc"
// PATH_NOSTDINC-NOT: /include
-/// Check include paths with -nobuiltininc
+/// Check include paths with -nobuiltininc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nobuiltininc 2>&1 | FileCheck %s --check-prefix=PATH_NOBUILTIN
@@ -37,7 +37,7 @@
// PATH_NOBUILTIN-NOT: "-internal-isystem" "[[RESOURCE]]/include"
// PATH_NOBUILTIN-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include"
-/// Check include paths with -nostdlibinc
+/// Check include paths with -nostdlibinc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nostdlibinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDLIBINC
@@ -48,7 +48,7 @@
// PATH_NOSTDLIBINC-SAME: "-internal-isystem" "[[RESOURCE]]/include"
// PATH_NOSTDLIBINC-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include"
-/// Check that PIC and PIE are enabled by default
+/// Check that PIC and PIE are enabled by default.
// RUN: %clang -c %s --target=x86_64-unkown-serenity -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-PIE2
// RUN: %clang -c %s --target=aarch64-unkown-serenity -### 2>&1 \
@@ -60,7 +60,7 @@
// CHECK-PIE2-SAME: "-pic-level" "2"
// CHECK-PIE2-SAME: "-pic-is-pie"
-/// Check default linker args for each supported triple
+/// Check default linker args for each supported triple.
// RUN: %clang -### %s --target=x86_64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_X86_64,DEFAULT_LINKER
// SERENITY_X86_64: "-cc1" "-triple" "[[TRIPLE:x86_64-unknown-serenity]]"
@@ -80,13 +80,13 @@
// DEFAULT_LINKER-SAME: "[[RESOURCE]]/lib/[[TRIPLE]]/libclang_rt.builtins.a"
// DEFAULT_LINKER-SAME: "-lc" "[[RESOURCE]]/lib/[[TRIPLE]]/clang_rt.crtend.o"
-/// Check if the sysroot is passed to the linker
+/// Check if the sysroot is passed to the linker.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=TestSysroot \
// RUN: -static-pie 2>&1 | FileCheck %s --check-prefix=LINKER_SYSROOT
// LINKER_SYSROOT: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
// LINKER_SYSROOT-SAME: "--sysroot=TestSysroot"
-/// -static-pie suppresses -dynamic-linker
+/// -static-pie suppresses -dynamic-linker.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
// RUN: -static-pie 2>&1 | FileCheck %s --check-prefix=STATIC_PIE
// STATIC_PIE: "-static" "-pie"
@@ -97,7 +97,7 @@
// STATIC_PIE-SAME: "crt0.o" "crtbeginS.o"
// STATIC_PIE-SAME: "-lc" "crtendS.o"
-/// -shared forces use of shared crt files
+/// -shared forces use of shared crt files.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
// RUN: -shared 2>&1 | FileCheck %s --check-prefix=SHARED
// SHARED: "-shared"
@@ -107,7 +107,7 @@
// SHARED-SAME: "crtbeginS.o"
// SHARED-SAME: "-lc" "crtendS.o"
-/// -static forces use of static crt files
+/// -static forces use of static crt files.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
// RUN: -static 2>&1 | FileCheck %s --check-prefix=STATIC
// STATIC: "-static"
@@ -116,7 +116,7 @@
// STATIC-SAME: "crt0.o" "crtbeginS.o"
// STATIC-SAME: "-lc" "crtendS.o"
-/// -rdynamic passes -export-dynamic
+/// -rdynamic passes -export-dynamic.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot= -resource-dir= \
// RUN: -rdynamic 2>&1 | FileCheck %s --check-prefix=RDYNAMIC,RDYNAMIC_SHARED
// RDYNAMIC: "-export-dynamic" "-pie"
@@ -132,7 +132,7 @@
// RDYNAMIC_SHARED-SAME: "crt0.o" "crtbeginS.o"
// RDYNAMIC_SHARED-SAME: "-lc" "crtendS.o"
-/// -nostdlib suppresses default -l and crt*.o
+/// -nostdlib suppresses default -l and crt*.o.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir= \
// RUN: -nostdlib --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTDLIB
@@ -144,7 +144,7 @@
// NOSTDLIB-NOT: libclang_rt.builtins
// NOSTDLIB-NOT: crt{{[^./]+}}.o
-// -nostartfiles suppresses crt*.o, but not default -l
+/// -nostartfiles suppresses crt*.o, but not default -l.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -nostartfiles --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTARTFILES
@@ -171,7 +171,7 @@
// RELOCATABLE-NOT: crt{{[^./]+}}.o
// RELOCATABLE-NOT: libclang_rt.builtins
-/// -nolibc suppresses -lc but not other default -l
+/// -nolibc suppresses -lc but not other default -l.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -nolibc --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOLIBC
@@ -184,14 +184,14 @@
// NOLIBC: "[[RESOURCE:[^"]+]]/lib/x86_64-unknown-serenity/libclang_rt.builtins.a"
// NOLIBC: "crtendS.o"
-/// -fsanitize=undefined redirects to Serenity-custom UBSAN runtime
+/// -fsanitize=undefined redirects to Serenity-custom UBSAN runtime.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsanitize=undefined --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=UBSAN
// UBSAN-NOT: "libclang_rt.ubsan"
// UBSAN: "-lubsan"
-/// C++ stdlib behavior
+/// Check C++ stdlib behavior.
// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
// RUN: 2>&1 | FileCheck %s --check-prefix=DEFAULT_LIBCXX
// DEFAULT_LIBCXX: "-dynamic-linker" "/usr/lib/Loader.so" "--eh-frame-hdr"
@@ -234,7 +234,7 @@
// NO_LIBCXX-NOT: "-lc++"
// NO_LIBCXX-SAME: "-lc" "crtendS.o"
-/// Check that unwind tables are enabled
+/// Check that unwind tables are enabled.
// RUN: %clang --target=x86_64-unknown-serenity -### -S %s 2>&1 | \
// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
// RUN: %clang --target=aarch64-unknown-serenity -### -S %s 2>&1 | \
@@ -243,8 +243,7 @@
// RUN: FileCheck -check-prefix=UNWIND-TABLES %s
// UNWIND-TABLES: "-funwind-tables=2"
-/// Check that parameters are forwarded to the linker
-
+/// Check that parameters are forwarded to the linker.
// RUN: %clang --target=x86_64-unknown-serenity -### %s -L/foo -u bar -T script.ld -s -t -r 2>&1 \
// RUN: | FileCheck %s --check-prefix=LINK
// LINK: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
@@ -260,7 +259,7 @@
// COMPRESS: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
// COMPRESS: "--compress-debug-sections=zlib"
-/// Check LTO
+/// Check LTO.
// RUN: %clang --target=x86_64-unknown-serenity -flto %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=LTO_FULL
// LTO_FULL: "-plugin-opt=
>From 33b4f796d410c5feaa5be78f28394b4deb482a81 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 10:47:24 +0200
Subject: [PATCH 14/17] Only use ld.lld" to match the linker
---
clang/test/Driver/serenity.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index e578269976c01..56ccca2970de3 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -70,7 +70,7 @@
// RUN: %clang -### %s --target=riscv64-unknown-serenity -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck %s --check-prefix=SERENITY_RISCV64,DEFAULT_LINKER
// SERENITY_RISCV64: "-cc1" "-triple" "[[TRIPLE:riscv64-unknown-serenity]]"
-// DEFAULT_LINKER: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// DEFAULT_LINKER: ld.lld"
// DEFAULT_LINKER-SAME: "-pie"
// DEFAULT_LINKER-SAME: "-dynamic-linker" "/usr/lib/Loader.so" "--eh-frame-hdr"
// DEFAULT_LINKER-SAME: "-o" "a.out"
@@ -83,7 +83,7 @@
/// Check if the sysroot is passed to the linker.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=TestSysroot \
// RUN: -static-pie 2>&1 | FileCheck %s --check-prefix=LINKER_SYSROOT
-// LINKER_SYSROOT: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// LINKER_SYSROOT: ld.lld"
// LINKER_SYSROOT-SAME: "--sysroot=TestSysroot"
/// -static-pie suppresses -dynamic-linker.
@@ -246,7 +246,7 @@
/// Check that parameters are forwarded to the linker.
// RUN: %clang --target=x86_64-unknown-serenity -### %s -L/foo -u bar -T script.ld -s -t -r 2>&1 \
// RUN: | FileCheck %s --check-prefix=LINK
-// LINK: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// LINK: ld.lld"
// LINK-SAME: "-L/foo"
// LINK-SAME: "-u" "bar"
// LINK-SAME: "-T" "script.ld"
@@ -256,7 +256,7 @@
// RUN: %clang --target=x86_64-unknown-serenity -### %s -Wl,--compress-debug-sections=zlib 2>&1 \
// RUN: | FileCheck %s --check-prefix=COMPRESS
-// COMPRESS: "{{(.*[^-.0-9A-Z_a-z])?}}ld.lld"
+// COMPRESS: ld.lld"
// COMPRESS: "--compress-debug-sections=zlib"
/// Check LTO.
>From b6a0b1dfe0053705646b33cb649f89ece5ea0e21 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 11:14:45 +0200
Subject: [PATCH 15/17] Remove Inputs/serenity_trere/usr/local/.keep
I forgot to do that in 02d03ead.
---
clang/test/Driver/Inputs/serenity_tree/usr/local/.keep | 0
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 clang/test/Driver/Inputs/serenity_tree/usr/local/.keep
diff --git a/clang/test/Driver/Inputs/serenity_tree/usr/local/.keep b/clang/test/Driver/Inputs/serenity_tree/usr/local/.keep
deleted file mode 100644
index e69de29bb2d1d..0000000000000
>From eeafbf9870f77988d5575452266e98cd7b551ff8 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 11:10:16 +0200
Subject: [PATCH 16/17] Stop passing -ccc-install-dir to tests
This removes all remaining references to Inputs/serenity/usr/local.
---
clang/test/Driver/serenity.cpp | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index 56ccca2970de3..e752cb8edb3e0 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -2,15 +2,15 @@
/// Check default header and linker paths for each supported triple.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
// RUN: %clang -### %s --target=aarch64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
// RUN: %clang -### %s --target=riscv64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: 2>&1 | FileCheck %s --check-prefix=PATHS
// PATHS: "-resource-dir" "[[RESOURCE:[^"]+]]"
@@ -21,14 +21,14 @@
/// Check include paths with -nostdinc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nostdinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDINC
// PATH_NOSTDINC: "-nostdsysteminc" "-nobuiltininc"
// PATH_NOSTDINC-NOT: /include
/// Check include paths with -nobuiltininc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nobuiltininc 2>&1 | FileCheck %s --check-prefix=PATH_NOBUILTIN
// PATH_NOBUILTIN: "-nobuiltininc"
// PATH_NOBUILTIN-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
@@ -39,7 +39,7 @@
/// Check include paths with -nostdlibinc.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -fsyntax-only -nostdlibinc 2>&1 | FileCheck %s --check-prefix=PATH_NOSTDLIBINC
// PATH_NOSTDLIBINC: "-nostdsysteminc"
// PATH_NOSTDLIBINC-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
@@ -134,8 +134,8 @@
/// -nostdlib suppresses default -l and crt*.o.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir= \
-// RUN: -nostdlib --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTDLIB
+// RUN: -resource-dir= -nostdlib --rtlib=compiler-rt \
+// RUN: 2>&1 | FileCheck %s --check-prefix=NOSTDLIB
// NOSTDLIB: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
// NOSTDLIB-NOT: crt{{[^./]+}}.o
// NOSTDLIB: "-L
@@ -146,8 +146,8 @@
/// -nostartfiles suppresses crt*.o, but not default -l.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
-// RUN: -nostartfiles --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOSTARTFILES
+// RUN: -resource-dir=%S/Inputs/resource_dir -nostartfiles --rtlib=compiler-rt \
+// RUN: 2>&1 | FileCheck %s --check-prefix=NOSTARTFILES
// NOSTARTFILES: "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
// NOSTARTFILES-SAME: {{^}}
// NOSTARTFILES-NOT: crt{{[^./]+}}.o
@@ -159,8 +159,8 @@
/// -r suppresses -dynamic-linker, default -l, and crt*.o like -nostdlib.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
-// RUN: -r --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=RELOCATABLE
+// RUN: -resource-dir=%S/Inputs/resource_dir -r --rtlib=compiler-rt \
+// RUN: 2>&1 | FileCheck %s --check-prefix=RELOCATABLE
// RELOCATABLE-NOT: "-dynamic-linker"
// RELOCATABLE: "-internal-isystem"
// RELOCATABLE-SAME: {{^}} "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
@@ -173,8 +173,8 @@
/// -nolibc suppresses -lc but not other default -l.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
-// RUN: -nolibc --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=NOLIBC
+// RUN: -resource-dir=%S/Inputs/resource_dir -nolibc --rtlib=compiler-rt \
+// RUN: 2>&1 | FileCheck %s --check-prefix=NOLIBC
// NOLIBC: "-internal-isystem"
// NOLIBC-SAME: {{^}} "[[SYSROOT:[^"]+]]/usr/include/c++/v1"
// NOLIBC: "[[SYSROOT:[^"]+]]/usr/lib/crt0.o" "crtbeginS.o"
@@ -186,8 +186,8 @@
/// -fsanitize=undefined redirects to Serenity-custom UBSAN runtime.
// RUN: %clang -### %s --target=x86_64-unknown-serenity --sysroot=%S/Inputs/serenity_tree \
-// RUN: -ccc-install-dir %S/Inputs/serenity_tree/usr/local/bin -resource-dir=%S/Inputs/resource_dir \
-// RUN: -fsanitize=undefined --rtlib=compiler-rt 2>&1 | FileCheck %s --check-prefix=UBSAN
+// RUN: -resource-dir=%S/Inputs/resource_dir -fsanitize=undefined --rtlib=compiler-rt \
+// RUN: 2>&1 | FileCheck %s --check-prefix=UBSAN
// UBSAN-NOT: "libclang_rt.ubsan"
// UBSAN: "-lubsan"
>From 0b6d41fb49a5f4f2e186017565a13be63b9a3864 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Tue, 14 Apr 2026 11:30:22 +0200
Subject: [PATCH 17/17] Add a test for KSAN
---
clang/test/Driver/serenity.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/clang/test/Driver/serenity.cpp b/clang/test/Driver/serenity.cpp
index e752cb8edb3e0..a10fd03e8f056 100644
--- a/clang/test/Driver/serenity.cpp
+++ b/clang/test/Driver/serenity.cpp
@@ -191,6 +191,12 @@
// UBSAN-NOT: "libclang_rt.ubsan"
// UBSAN: "-lubsan"
+/// Support for KASAN.
+// RUN: %clang -target x86_64-unknown-serenity -fsanitize=kernel-address -### %s \
+// RUN: 2>&1 | FileCheck %s --check-prefix=KASAN
+// KASAN: "-fsanitize=kernel-address"
+// KASAN-SAME: "-fsanitize-recover=kernel-address"
+
/// Check C++ stdlib behavior.
// RUN: %clangxx -### %s --target=x86_64-unknown-serenity --sysroot="" -resource-dir= \
// RUN: 2>&1 | FileCheck %s --check-prefix=DEFAULT_LIBCXX
More information about the cfe-commits
mailing list