clang 24.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 bool IsPIE =
58 A ? A->getOption().matches(options::OPT_pie) : TC.isPIEDefault(Args);
59 if (IsPIE)
60 CmdArgs.push_back("-pie");
61 CmdArgs.push_back("-dynamic-linker");
62 CmdArgs.push_back(Args.MakeArgString(TC.getDynamicLinker(Args)));
63 }
64 }
65
66 CmdArgs.push_back("--eh-frame-hdr");
67
68 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
69 if (Output.isFilename()) {
70 CmdArgs.push_back("-o");
71 CmdArgs.push_back(Output.getFilename());
72 }
73
74 CmdArgs.push_back("-z");
75 CmdArgs.push_back("pack-relative-relocs");
76
77 bool HasNoStdLib = Args.hasArg(options::OPT_nostdlib, options::OPT_r);
78 bool HasNoStdLibXX = Args.hasArg(options::OPT_nostdlibxx);
79 bool HasNoLibC = Args.hasArg(options::OPT_nolibc);
80 bool HasNoStartFiles = Args.hasArg(options::OPT_nostartfiles);
81 bool HasNoDefaultLibs = Args.hasArg(options::OPT_nodefaultlibs);
82
83 bool ShouldLinkStartFiles = !HasNoStartFiles && !HasNoStdLib;
84 bool ShouldLinkCompilerRuntime = !HasNoDefaultLibs && !HasNoStdLib;
85 bool ShouldLinkLibC = !HasNoLibC && !HasNoStdLib && !HasNoDefaultLibs;
86 bool ShouldLinkLibCXX =
87 D.CCCIsCXX() && !HasNoStdLibXX && !HasNoStdLib && !HasNoDefaultLibs;
88
89 if (ShouldLinkStartFiles) {
90 if (!IsShared)
91 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o")));
92
93 std::string crtbegin_path;
94 if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
95 std::string crtbegin =
96 TC.getCompilerRT(Args, "crtbegin", ToolChain::FT_Object);
97 if (TC.getVFS().exists(crtbegin))
98 crtbegin_path = crtbegin;
99 }
100 if (crtbegin_path.empty())
101 crtbegin_path = TC.GetFilePath("crtbeginS.o");
102 CmdArgs.push_back(Args.MakeArgString(crtbegin_path));
103 }
104
105 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
106
107 TC.AddFilePathLibArgs(Args, CmdArgs);
108
109 if (auto LTO = TC.getLTOMode(Args); LTO != LTOK_None)
110 addLTOOptions(TC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin);
111
112 Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
113 options::OPT_t, options::OPT_r});
114
115 addLinkerCompressDebugSectionsOption(TC, Args, CmdArgs);
116
117 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
118
119 if (ShouldLinkCompilerRuntime) {
120 AddRunTimeLibs(TC, D, CmdArgs, Args);
121
122 // We supply our own sanitizer runtimes that output errors to the
123 // Kernel debug log as well as stderr.
124 // FIXME: Properly port clang/gcc sanitizers and use those instead.
125 const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
126 if (Sanitize.needsUbsanRt())
127 CmdArgs.push_back("-lubsan");
128 }
129
130 if (ShouldLinkLibCXX) {
131 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
132 !Args.hasArg(options::OPT_static);
133 CmdArgs.push_back("--push-state");
134 CmdArgs.push_back("--as-needed");
135 if (OnlyLibstdcxxStatic)
136 CmdArgs.push_back("-Bstatic");
137 TC.AddCXXStdlibLibArgs(Args, CmdArgs);
138 if (OnlyLibstdcxxStatic)
139 CmdArgs.push_back("-Bdynamic");
140 CmdArgs.push_back("--pop-state");
141 }
142
143 // Silence warnings when linking C code with a C++ '-stdlib' argument.
144 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
145
146 if (ShouldLinkLibC)
147 CmdArgs.push_back("-lc");
148
149 if (ShouldLinkStartFiles) {
150 std::string crtend_path;
151 if (TC.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT) {
152 std::string crtend =
153 TC.getCompilerRT(Args, "crtend", ToolChain::FT_Object);
154 if (TC.getVFS().exists(crtend))
155 crtend_path = crtend;
156 }
157 if (crtend_path.empty())
158 crtend_path = TC.GetFilePath("crtendS.o");
159 CmdArgs.push_back(Args.MakeArgString(crtend_path));
160 }
161
162 const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
163 C.addCommand(std::make_unique<Command>(JA, *this,
165 Exec, CmdArgs, Inputs, Output));
166}
167
170 Action::OffloadKind DeviceOffloadKind) const {
171 return ToolChain::getSupportedSanitizers(BA, DeviceOffloadKind) |
172 SanitizerKind::KernelAddress;
173}
174
175Serenity::Serenity(const Driver &D, const llvm::Triple &Triple,
176 const ArgList &Args)
177 : Generic_ELF(D, Triple, Args) {
178 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
179}
180
182 return new tools::serenity::Linker(*this);
183}
184
185void Serenity::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
186 ArgStringList &CC1Args) const {
187 const Driver &D = getDriver();
188
189 if (DriverArgs.hasArg(options::OPT_nostdinc))
190 return;
191
192 if (!DriverArgs.hasArg(options::OPT_nobuiltininc))
193 addSystemInclude(DriverArgs, CC1Args, concat(D.ResourceDir, "/include"));
194
195 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
196 return;
197
198 addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot, "/usr/include"));
199}
Compilation - A set of tasks to perform for a single driver invocation.
Definition Compilation.h:46
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition Driver.h:95
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:326
virtual SanitizerMask getSupportedSanitizers(BoundArch BA, Action::OffloadKind DeviceOffloadKind) const
Return sanitizers which are available in this toolchain.
const Driver & getDriver() const
Definition ToolChain.h:286
static std::string concat(StringRef Path, const Twine &A, const Twine &B="", const Twine &C="", const Twine &D="")
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:181
SanitizerMask getSupportedSanitizers(BoundArch BA, Action::OffloadKind DeviceOffloadKind) const override
Return sanitizers which are available in this toolchain.
Definition Serenity.cpp:169
Serenity(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition Serenity.cpp:175
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:185
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:51
The JSON file list parser is used to communicate input to InstallAPI.
Represents a bound architecture for offload / multiple architecture compilation.
static constexpr ResponseFileSupport AtFileCurCP()
Definition Job.h:93