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