1 | //===--- Haiku.cpp - Haiku ToolChain Implementations ------------*- 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 "Haiku.h" |
10 | #include "clang/Config/config.h" |
11 | #include "clang/Driver/CommonArgs.h" |
12 | #include "clang/Driver/Compilation.h" |
13 | #include "clang/Driver/SanitizerArgs.h" |
14 | #include "llvm/Support/Path.h" |
15 | |
16 | using namespace clang::driver; |
17 | using namespace clang::driver::tools; |
18 | using namespace clang::driver::toolchains; |
19 | using namespace clang; |
20 | using namespace llvm::opt; |
21 | |
22 | void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
23 | const InputInfo &Output, |
24 | const InputInfoList &Inputs, |
25 | const ArgList &Args, |
26 | const char *LinkingOutput) const { |
27 | const auto &ToolChain = static_cast<const Haiku &>(getToolChain()); |
28 | const Driver &D = ToolChain.getDriver(); |
29 | const llvm::Triple &Triple = ToolChain.getTriple(); |
30 | const bool Static = Args.hasArg(options::OPT_static); |
31 | const bool Shared = Args.hasArg(options::OPT_shared); |
32 | ArgStringList CmdArgs; |
33 | |
34 | // Silence warning for "clang -g foo.o -o foo" |
35 | Args.ClaimAllArgs(options::OPT_g_Group); |
36 | // and "clang -emit-llvm foo.o -o foo" |
37 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
38 | // and for "clang -w foo.o -o foo". Other warning options are already |
39 | // handled somewhere else. |
40 | Args.ClaimAllArgs(options::OPT_w); |
41 | |
42 | // Silence warning for "clang -pie foo.o -o foo" |
43 | Args.ClaimAllArgs(options::OPT_pie); |
44 | |
45 | // -rdynamic is a no-op with Haiku. Claim argument to avoid warning. |
46 | Args.ClaimAllArgs(options::OPT_rdynamic); |
47 | |
48 | if (!D.SysRoot.empty()) |
49 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: "--sysroot=" + D.SysRoot)); |
50 | |
51 | CmdArgs.push_back(Elt: "--eh-frame-hdr" ); |
52 | if (Static) { |
53 | CmdArgs.push_back(Elt: "-Bstatic" ); |
54 | } else { |
55 | if (Shared) |
56 | CmdArgs.push_back(Elt: "-shared" ); |
57 | CmdArgs.push_back(Elt: "--enable-new-dtags" ); |
58 | } |
59 | |
60 | CmdArgs.push_back(Elt: "-shared" ); |
61 | |
62 | if (!Shared) |
63 | CmdArgs.push_back(Elt: "--no-undefined" ); |
64 | |
65 | if (Triple.isRISCV64()) { |
66 | CmdArgs.push_back(Elt: "-X" ); |
67 | if (Args.hasArg(options::OPT_mno_relax)) |
68 | CmdArgs.push_back(Elt: "--no-relax" ); |
69 | } |
70 | |
71 | assert((Output.isFilename() || Output.isNothing()) && "Invalid output." ); |
72 | if (Output.isFilename()) { |
73 | CmdArgs.push_back(Elt: "-o" ); |
74 | CmdArgs.push_back(Elt: Output.getFilename()); |
75 | } |
76 | |
77 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, |
78 | options::OPT_r)) { |
79 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "crti.o" ))); |
80 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "crtbeginS.o" ))); |
81 | if (!Shared) |
82 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "start_dyn.o" ))); |
83 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "init_term_dyn.o" ))); |
84 | } |
85 | |
86 | Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, |
87 | options::OPT_s, options::OPT_t}); |
88 | ToolChain.AddFilePathLibArgs(Args, CmdArgs); |
89 | |
90 | if (D.isUsingLTO()) |
91 | addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, |
92 | IsThinLTO: D.getLTOMode() == LTOK_Thin); |
93 | |
94 | bool NeedsSanitizerDeps = addSanitizerRuntimes(TC: ToolChain, Args, CmdArgs); |
95 | addLinkerCompressDebugSectionsOption(TC: ToolChain, Args, CmdArgs); |
96 | AddLinkerInputs(TC: ToolChain, Inputs, Args, CmdArgs, JA); |
97 | |
98 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, |
99 | options::OPT_r)) { |
100 | // Use the static OpenMP runtime with -static-openmp |
101 | bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; |
102 | addOpenMPRuntime(C, CmdArgs, TC: ToolChain, Args, ForceStaticHostRuntime: StaticOpenMP); |
103 | |
104 | if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args)) |
105 | ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); |
106 | |
107 | // Silence warnings when linking C code with a C++ '-stdlib' argument. |
108 | Args.ClaimAllArgs(options::OPT_stdlib_EQ); |
109 | |
110 | // Additional linker set-up and flags for Fortran. This is required in order |
111 | // to generate executables. As Fortran runtime depends on the C runtime, |
112 | // these dependencies need to be listed before the C runtime below (i.e. |
113 | // AddRunTimeLibs). |
114 | if (D.IsFlangMode() && |
115 | !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
116 | ToolChain.addFortranRuntimeLibraryPath(Args, CmdArgs); |
117 | ToolChain.addFortranRuntimeLibs(Args, CmdArgs); |
118 | } |
119 | |
120 | if (NeedsSanitizerDeps) |
121 | linkSanitizerRuntimeDeps(TC: ToolChain, Args, CmdArgs); |
122 | |
123 | CmdArgs.push_back(Elt: "-lgcc" ); |
124 | |
125 | CmdArgs.push_back(Elt: "--push-state" ); |
126 | CmdArgs.push_back(Elt: "--as-needed" ); |
127 | CmdArgs.push_back(Elt: "-lgcc_s" ); |
128 | CmdArgs.push_back(Elt: "--no-as-needed" ); |
129 | CmdArgs.push_back(Elt: "--pop-state" ); |
130 | |
131 | CmdArgs.push_back(Elt: "-lroot" ); |
132 | |
133 | CmdArgs.push_back(Elt: "-lgcc" ); |
134 | |
135 | CmdArgs.push_back(Elt: "--push-state" ); |
136 | CmdArgs.push_back(Elt: "--as-needed" ); |
137 | CmdArgs.push_back(Elt: "-lgcc_s" ); |
138 | CmdArgs.push_back(Elt: "--no-as-needed" ); |
139 | CmdArgs.push_back(Elt: "--pop-state" ); |
140 | } |
141 | |
142 | // No need to do anything for pthreads. Claim argument to avoid warning. |
143 | Args.claimAllArgs(options::OPT_pthread, options::OPT_pthreads); |
144 | |
145 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, |
146 | options::OPT_r)) { |
147 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "crtendS.o" ))); |
148 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "crtn.o" ))); |
149 | } |
150 | |
151 | ToolChain.addProfileRTLibs(Args, CmdArgs); |
152 | |
153 | const char *Exec = Args.MakeArgString(Str: getToolChain().GetLinkerPath()); |
154 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
155 | args: ResponseFileSupport::AtFileCurCP(), |
156 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
157 | } |
158 | |
159 | /// Haiku - Haiku tool chain which can call as(1) and ld(1) directly. |
160 | |
161 | Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) |
162 | : Generic_ELF(D, Triple, Args) { |
163 | |
164 | GCCInstallation.init(TargetTriple: Triple, Args); |
165 | |
166 | getFilePaths().push_back(Elt: concat(Path: getDriver().SysRoot, A: "/boot/system/lib" )); |
167 | getFilePaths().push_back(Elt: concat(Path: getDriver().SysRoot, A: "/boot/system/develop/lib" )); |
168 | |
169 | if (GCCInstallation.isValid()) |
170 | getFilePaths().push_back(Elt: GCCInstallation.getInstallPath().str()); |
171 | } |
172 | |
173 | void Haiku::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, |
174 | llvm::opt::ArgStringList &CC1Args) const { |
175 | const Driver &D = getDriver(); |
176 | |
177 | if (DriverArgs.hasArg(options::OPT_nostdinc)) |
178 | return; |
179 | |
180 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
181 | SmallString<128> Dir(D.ResourceDir); |
182 | llvm::sys::path::append(path&: Dir, a: "include" ); |
183 | addSystemInclude(DriverArgs, CC1Args, Path: Dir.str()); |
184 | } |
185 | |
186 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
187 | return; |
188 | |
189 | // Add dirs specified via 'configure --with-c-include-dirs'. |
190 | StringRef CIncludeDirs(C_INCLUDE_DIRS); |
191 | if (!CIncludeDirs.empty()) { |
192 | SmallVector<StringRef, 5> dirs; |
193 | CIncludeDirs.split(A&: dirs, Separator: ":" ); |
194 | for (StringRef dir : dirs) { |
195 | StringRef Prefix = |
196 | llvm::sys::path::is_absolute(path: dir) ? StringRef(D.SysRoot) : "" ; |
197 | addExternCSystemInclude(DriverArgs, CC1Args, Path: Prefix + dir); |
198 | } |
199 | return; |
200 | } |
201 | |
202 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
203 | A: "/boot/system/non-packaged/develop/headers" )); |
204 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
205 | A: "/boot/system/develop/headers/os" )); |
206 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
207 | A: "/boot/system/develop/headers/os/app" )); |
208 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
209 | A: "/boot/system/develop/headers/os/device" )); |
210 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
211 | A: "/boot/system/develop/headers/os/drivers" )); |
212 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
213 | A: "/boot/system/develop/headers/os/game" )); |
214 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
215 | A: "/boot/system/develop/headers/os/interface" )); |
216 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
217 | A: "/boot/system/develop/headers/os/kernel" )); |
218 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
219 | A: "/boot/system/develop/headers/os/locale" )); |
220 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
221 | A: "/boot/system/develop/headers/os/mail" )); |
222 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
223 | A: "/boot/system/develop/headers/os/media" )); |
224 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
225 | A: "/boot/system/develop/headers/os/midi" )); |
226 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
227 | A: "/boot/system/develop/headers/os/midi2" )); |
228 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
229 | A: "/boot/system/develop/headers/os/net" )); |
230 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
231 | A: "/boot/system/develop/headers/os/opengl" )); |
232 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
233 | A: "/boot/system/develop/headers/os/storage" )); |
234 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
235 | A: "/boot/system/develop/headers/os/support" )); |
236 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
237 | A: "/boot/system/develop/headers/os/translation" )); |
238 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
239 | A: "/boot/system/develop/headers/os/add-ons/graphics" )); |
240 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
241 | A: "/boot/system/develop/headers/os/add-ons/input_server" )); |
242 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
243 | A: "/boot/system/develop/headers/os/add-ons/mail_daemon" )); |
244 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
245 | A: "/boot/system/develop/headers/os/add-ons/registrar" )); |
246 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
247 | A: "/boot/system/develop/headers/os/add-ons/screen_saver" )); |
248 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
249 | A: "/boot/system/develop/headers/os/add-ons/tracker" )); |
250 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
251 | A: "/boot/system/develop/headers/os/be_apps/Deskbar" )); |
252 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
253 | A: "/boot/system/develop/headers/os/be_apps/NetPositive" )); |
254 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
255 | A: "/boot/system/develop/headers/os/be_apps/Tracker" )); |
256 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
257 | A: "/boot/system/develop/headers/3rdparty" )); |
258 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
259 | A: "/boot/system/develop/headers/bsd" )); |
260 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
261 | A: "/boot/system/develop/headers/glibc" )); |
262 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
263 | A: "/boot/system/develop/headers/gnu" )); |
264 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
265 | A: "/boot/system/develop/headers/posix" )); |
266 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
267 | A: "/boot/system/develop/headers/gcc/include" )); |
268 | addSystemInclude(DriverArgs, CC1Args, Path: concat(Path: D.SysRoot, |
269 | A: "/boot/system/develop/headers" )); |
270 | } |
271 | |
272 | void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, |
273 | llvm::opt::ArgStringList &CC1Args) const { |
274 | addSystemInclude(DriverArgs, CC1Args, |
275 | Path: concat(Path: getDriver().SysRoot, A: "/boot/system/develop/headers/c++/v1" )); |
276 | } |
277 | |
278 | Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); } |
279 | |
280 | bool Haiku::HasNativeLLVMSupport() const { return true; } |
281 | |
282 | SanitizerMask Haiku::getSupportedSanitizers() const { |
283 | SanitizerMask Res = ToolChain::getSupportedSanitizers(); |
284 | |
285 | Res |= SanitizerKind::Address; |
286 | |
287 | return Res; |
288 | } |
289 | |