clang 23.0.0git
Serenity.cpp
Go to the documentation of this file.
1//===---- Serenity.cpp - SerenityOS ToolChain Implementation ----*- 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 "Serenity.h"
10#include "clang/Config/config.h"
13#include "clang/Driver/Driver.h"
16#include "llvm/Option/ArgList.h"
17#include "llvm/Support/VirtualFileSystem.h"
18#include <string>
19
20using namespace clang::driver;
21using namespace clang::driver::toolchains;
22using namespace clang;
23using namespace llvm::opt;
24
26 const InputInfo &Output,
27 const InputInfoList &Inputs,
28 const ArgList &Args,
29 const char *LinkingOutput) const {
30 const auto &TC = static_cast<Generic_ELF const &>(getToolChain());
31 const auto &D = TC.getDriver();
32 const bool IsShared = Args.hasArg(options::OPT_shared);
33 const bool IsStatic =
34 Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_static_pie);
35 const bool IsStaticPIE = Args.hasArg(options::OPT_static_pie);
36 ArgStringList CmdArgs;
37
38 if (!D.SysRoot.empty())
39 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
40
41 if (IsShared)
42 CmdArgs.push_back("-shared");
43
44 if (IsStaticPIE) {
45 CmdArgs.push_back("-static");
46 CmdArgs.push_back("-pie");
47 CmdArgs.push_back("--no-dynamic-linker");
48 CmdArgs.push_back("-z");
49 CmdArgs.push_back("text");
50 } else if (IsStatic) {
51 CmdArgs.push_back("-static");
52 } else if (!Args.hasArg(options::OPT_r)) {
53 if (Args.hasArg(options::OPT_rdynamic))
54 CmdArgs.push_back("-export-dynamic");
55 if (!IsShared) {
56 Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
57 options::OPT_nopie);
58 bool IsPIE =
59 A ? A->getOption().matches(options::OPT_pie) : TC.isPIEDefault(Args);
60 if (IsPIE)
61 CmdArgs.push_back("-pie");
62 CmdArgs.push_back("-dynamic-linker");
63 CmdArgs.push_back(Args.MakeArgString(TC.getDynamicLinker(Args)));
64 }
65 }
66
67 CmdArgs.push_back("--eh-frame-hdr");
68
69 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
70 if (Output.isFilename()) {
71 CmdArgs.push_back("-o");
72 CmdArgs.push_back(Output.getFilename());
73 }
74
75 CmdArgs.push_back("-z");
76 CmdArgs.push_back("pack-relative-relocs");
77
78 bool HasNoStdLib = Args.hasArg(options::OPT_nostdlib, options::OPT_r);
79 bool HasNoStdLibXX = Args.hasArg(options::OPT_nostdlibxx);
80 bool HasNoLibC = Args.hasArg(options::OPT_nolibc);
81 bool HasNoStartFiles = Args.hasArg(options::OPT_nostartfiles);
82 bool HasNoDefaultLibs = Args.hasArg(options::OPT_nodefaultlibs);
83
84 bool ShouldLinkStartFiles = !HasNoStartFiles && !HasNoStdLib;
85 bool ShouldLinkCompilerRuntime = !HasNoDefaultLibs && !HasNoStdLib;
86 bool ShouldLinkLibC = !HasNoLibC && !HasNoStdLib && !HasNoDefaultLibs;
87 bool ShouldLinkLibCXX =
88 D.CCCIsCXX() && !HasNoStdLibXX && !HasNoStdLib && !HasNoDefaultLibs;
89
90 if (ShouldLinkStartFiles) {
91 if (!IsShared)
92 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o")));
93
94 std::string crtbegin_path;
95 if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
96 std::string crtbegin =
97 TC.getCompilerRT(Args, "crtbegin", ToolChain::FT_Object);
98 if (TC.getVFS().exists(crtbegin))
99 crtbegin_path = crtbegin;
100 }
101 if (crtbegin_path.empty())
102 crtbegin_path = TC.GetFilePath("crtbeginS.o");
103 CmdArgs.push_back(Args.MakeArgString(crtbegin_path));
104 }
105
106 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
107
108 TC.AddFilePathLibArgs(Args, CmdArgs);
109
110 if (D.isUsingLTO())
111 addLTOOptions(TC, Args, CmdArgs, Output, Inputs,
112 D.getLTOMode() == LTOK_Thin);
113
114 Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
115 options::OPT_t, options::OPT_r});
116
117 addLinkerCompressDebugSectionsOption(TC, Args, CmdArgs);
118
119 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
120
121 if (ShouldLinkCompilerRuntime) {
122 AddRunTimeLibs(TC, D, CmdArgs, Args);
123
124 // We supply our own sanitizer runtimes that output errors to the
125 // Kernel debug log as well as stderr.
126 // FIXME: Properly port clang/gcc sanitizers and use those instead.
127 const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
128 if (Sanitize.needsUbsanRt())
129 CmdArgs.push_back("-lubsan");
130 }
131
132 if (ShouldLinkLibCXX) {
133 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
134 !Args.hasArg(options::OPT_static);
135 CmdArgs.push_back("--push-state");
136 CmdArgs.push_back("--as-needed");
137 if (OnlyLibstdcxxStatic)
138 CmdArgs.push_back("-Bstatic");
139 TC.AddCXXStdlibLibArgs(Args, CmdArgs);
140 if (OnlyLibstdcxxStatic)
141 CmdArgs.push_back("-Bdynamic");
142 CmdArgs.push_back("--pop-state");
143 }
144
145 // Silence warnings when linking C code with a C++ '-stdlib' argument.
146 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
147
148 if (ShouldLinkLibC)
149 CmdArgs.push_back("-lc");
150
151 if (ShouldLinkStartFiles) {
152 std::string crtend_path;
153 if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
154 std::string crtend =
155 TC.getCompilerRT(Args, "crtend", ToolChain::FT_Object);
156 if (TC.getVFS().exists(crtend))
157 crtend_path = crtend;
158 }
159 if (crtend_path.empty())
160 crtend_path = TC.GetFilePath("crtendS.o");
161 CmdArgs.push_back(Args.MakeArgString(crtend_path));
162 }
163
164 const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
165 C.addCommand(std::make_unique<Command>(JA, *this,
167 Exec, CmdArgs, Inputs, Output));
168}
169
171 return ToolChain::getSupportedSanitizers() | SanitizerKind::KernelAddress;
172}
173
174Serenity::Serenity(const Driver &D, const llvm::Triple &Triple,
175 const ArgList &Args)
176 : Generic_ELF(D, Triple, Args) {
177 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
178}
179
181 return new tools::serenity::Linker(*this);
182}
183
184void Serenity::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
185 ArgStringList &CC1Args) const {
186 const Driver &D = getDriver();
187
188 if (DriverArgs.hasArg(options::OPT_nostdinc))
189 return;
190
191 if (!DriverArgs.hasArg(options::OPT_nobuiltininc))
192 addSystemInclude(DriverArgs, CC1Args, concat(D.ResourceDir, "/include"));
193
194 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
195 return;
196
197 addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot, "/usr/include"));
198}
Compilation - A set of tasks to perform for a single driver invocation.
Definition Compilation.h:45
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition Driver.h:99
InputInfo - Wrapper for information about an input source.
Definition InputInfo.h:22
const char * getFilename() const
Definition InputInfo.h:83
bool isNothing() const
Definition InputInfo.h:74
bool isFilename() const
Definition InputInfo.h:75
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
path_list & getFilePaths()
Definition ToolChain.h:317
const Driver & getDriver() const
Definition ToolChain.h:277
static std::string concat(StringRef Path, const Twine &A, const Twine &B="", const Twine &C="", const Twine &D="")
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Tool - Information on a specific compilation tool.
Definition Tool.h:32
const ToolChain & getToolChain() const
Definition Tool.h:52
Generic_ELF(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition Gnu.h:439
Tool * buildLinker() const override
Definition Serenity.cpp:180
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition Serenity.cpp:170
Serenity(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition Serenity.cpp:174
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add the clang cc1 arguments for system include paths.
Definition Serenity.cpp:184
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition Serenity.cpp:25
void addLTOOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs, bool IsThinLTO)
void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args)
void addLinkerCompressDebugSectionsOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
SmallVector< InputInfo, 4 > InputInfoList
Definition Driver.h:50
The JSON file list parser is used to communicate input to InstallAPI.
static constexpr ResponseFileSupport AtFileCurCP()
Definition Job.h:92