/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Hexagon.cpp - Hexagon 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 "Hexagon.h" |
10 | | #include "CommonArgs.h" |
11 | | #include "InputInfo.h" |
12 | | #include "clang/Driver/Compilation.h" |
13 | | #include "clang/Driver/Driver.h" |
14 | | #include "clang/Driver/DriverDiagnostic.h" |
15 | | #include "clang/Driver/Options.h" |
16 | | #include "llvm/ADT/StringExtras.h" |
17 | | #include "llvm/Option/ArgList.h" |
18 | | #include "llvm/Support/FileSystem.h" |
19 | | #include "llvm/Support/Path.h" |
20 | | #include "llvm/Support/VirtualFileSystem.h" |
21 | | |
22 | | using namespace clang::driver; |
23 | | using namespace clang::driver::tools; |
24 | | using namespace clang::driver::toolchains; |
25 | | using namespace clang; |
26 | | using namespace llvm::opt; |
27 | | |
28 | | // Default hvx-length for various versions. |
29 | 10 | static StringRef getDefaultHvxLength(StringRef Cpu) { |
30 | 10 | return llvm::StringSwitch<StringRef>(Cpu) |
31 | 10 | .Case("v60", "64b") |
32 | 10 | .Case("v62", "64b") |
33 | 10 | .Case("v65", "64b") |
34 | 10 | .Default("128b"); |
35 | 10 | } |
36 | | |
37 | 96 | static void handleHVXWarnings(const Driver &D, const ArgList &Args) { |
38 | | // Handle the unsupported values passed to mhvx-length. |
39 | 96 | if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) { |
40 | 10 | StringRef Val = A->getValue(); |
41 | 10 | if (!Val.equals_lower("64b") && !Val.equals_lower("128b")7 ) |
42 | 2 | D.Diag(diag::err_drv_unsupported_option_argument) |
43 | 2 | << A->getOption().getName() << Val; |
44 | 10 | } |
45 | 96 | } |
46 | | |
47 | | // Handle hvx target features explicitly. |
48 | | static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args, |
49 | | std::vector<StringRef> &Features, |
50 | 96 | StringRef Cpu, bool &HasHVX) { |
51 | | // Handle HVX warnings. |
52 | 96 | handleHVXWarnings(D, Args); |
53 | | |
54 | | // Add the +hvx* features based on commandline flags. |
55 | 96 | StringRef HVXFeature, HVXLength; |
56 | | |
57 | | // Handle -mhvx, -mhvx=, -mno-hvx. |
58 | 96 | if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx, |
59 | 20 | options::OPT_mhexagon_hvx, |
60 | 20 | options::OPT_mhexagon_hvx_EQ)) { |
61 | 20 | if (A->getOption().matches(options::OPT_mno_hexagon_hvx)) |
62 | 2 | return; |
63 | 18 | if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) { |
64 | 2 | HasHVX = true; |
65 | 2 | HVXFeature = Cpu = A->getValue(); |
66 | 2 | HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower()); |
67 | 16 | } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) { |
68 | 16 | HasHVX = true; |
69 | 16 | HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu); |
70 | 16 | } |
71 | 18 | Features.push_back(HVXFeature); |
72 | 18 | } |
73 | | |
74 | | // Handle -mhvx-length=. |
75 | 94 | if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) { |
76 | | // These flags are valid only if HVX in enabled. |
77 | 10 | if (!HasHVX) |
78 | 2 | D.Diag(diag::err_drv_invalid_hvx_length); |
79 | 8 | else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ)) |
80 | 8 | HVXLength = A->getValue(); |
81 | 10 | } |
82 | | // Default hvx-length based on Cpu. |
83 | 84 | else if (HasHVX) |
84 | 10 | HVXLength = getDefaultHvxLength(Cpu); |
85 | | |
86 | 94 | if (!HVXLength.empty()) { |
87 | 18 | HVXFeature = |
88 | 18 | Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower()); |
89 | 18 | Features.push_back(HVXFeature); |
90 | 18 | } |
91 | 94 | } |
92 | | |
93 | | // Hexagon target features. |
94 | | void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args, |
95 | 96 | std::vector<StringRef> &Features) { |
96 | 96 | handleTargetFeaturesGroup(Args, Features, |
97 | 96 | options::OPT_m_hexagon_Features_Group); |
98 | | |
99 | 96 | bool UseLongCalls = false; |
100 | 96 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
101 | 2 | options::OPT_mno_long_calls)) { |
102 | 2 | if (A->getOption().matches(options::OPT_mlong_calls)) |
103 | 1 | UseLongCalls = true; |
104 | 2 | } |
105 | | |
106 | 95 | Features.push_back(UseLongCalls ? "+long-calls"1 : "-long-calls"); |
107 | | |
108 | 96 | bool HasHVX = false; |
109 | 96 | StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args)); |
110 | | // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors |
111 | | // have no dependency on micro-architecture. |
112 | 96 | const bool TinyCore = Cpu.contains('t'); |
113 | | |
114 | 96 | if (TinyCore) |
115 | 1 | Cpu = Cpu.take_front(Cpu.size() - 1); |
116 | | |
117 | 96 | handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX); |
118 | | |
119 | 96 | if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX2 ) |
120 | 2 | D.Diag(diag::warn_drv_vectorize_needs_hvx); |
121 | 96 | } |
122 | | |
123 | | // Hexagon tools start. |
124 | | void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA, |
125 | 5 | ArgStringList &CmdArgs) const { |
126 | 5 | } |
127 | | |
128 | | void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
129 | | const InputInfo &Output, |
130 | | const InputInfoList &Inputs, |
131 | | const ArgList &Args, |
132 | 5 | const char *LinkingOutput) const { |
133 | 5 | claimNoWarnArgs(Args); |
134 | | |
135 | 5 | auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); |
136 | 5 | const Driver &D = HTC.getDriver(); |
137 | 5 | ArgStringList CmdArgs; |
138 | | |
139 | 5 | CmdArgs.push_back("--arch=hexagon"); |
140 | | |
141 | 5 | RenderExtraToolArgs(JA, CmdArgs); |
142 | | |
143 | 5 | const char *AsName = "llvm-mc"; |
144 | 5 | CmdArgs.push_back("-filetype=obj"); |
145 | 5 | CmdArgs.push_back(Args.MakeArgString( |
146 | 5 | "-mcpu=hexagon" + |
147 | 5 | toolchains::HexagonToolChain::GetTargetCPUVersion(Args))); |
148 | | |
149 | 5 | if (Output.isFilename()) { |
150 | 5 | CmdArgs.push_back("-o"); |
151 | 5 | CmdArgs.push_back(Output.getFilename()); |
152 | 0 | } else { |
153 | 0 | assert(Output.isNothing() && "Unexpected output"); |
154 | 0 | CmdArgs.push_back("-fsyntax-only"); |
155 | 0 | } |
156 | | |
157 | 5 | if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { |
158 | 3 | CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue()))); |
159 | 3 | } |
160 | | |
161 | 5 | Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
162 | | |
163 | | // Only pass -x if gcc will understand it; otherwise hope gcc |
164 | | // understands the suffix correctly. The main use case this would go |
165 | | // wrong in is for linker inputs if they happened to have an odd |
166 | | // suffix; really the only way to get this to happen is a command |
167 | | // like '-x foobar a.c' which will treat a.c like a linker input. |
168 | | // |
169 | | // FIXME: For the linker case specifically, can we safely convert |
170 | | // inputs into '-Wl,' options? |
171 | 5 | for (const auto &II : Inputs) { |
172 | | // Don't try to pass LLVM or AST inputs to a generic gcc. |
173 | 5 | if (types::isLLVMIR(II.getType())) |
174 | 0 | D.Diag(clang::diag::err_drv_no_linker_llvm_support) |
175 | 0 | << HTC.getTripleString(); |
176 | 5 | else if (II.getType() == types::TY_AST) |
177 | 0 | D.Diag(clang::diag::err_drv_no_ast_support) |
178 | 0 | << HTC.getTripleString(); |
179 | 5 | else if (II.getType() == types::TY_ModuleFile) |
180 | 0 | D.Diag(diag::err_drv_no_module_support) |
181 | 0 | << HTC.getTripleString(); |
182 | | |
183 | 5 | if (II.isFilename()) |
184 | 5 | CmdArgs.push_back(II.getFilename()); |
185 | 0 | else |
186 | | // Don't render as input, we need gcc to do the translations. |
187 | | // FIXME: What is this? |
188 | 0 | II.getInputArg().render(Args, CmdArgs); |
189 | 5 | } |
190 | | |
191 | 5 | auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); |
192 | 5 | C.addCommand(std::make_unique<Command>(JA, *this, |
193 | 5 | ResponseFileSupport::AtFileCurCP(), |
194 | 5 | Exec, CmdArgs, Inputs, Output)); |
195 | 5 | } |
196 | | |
197 | | void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, |
198 | 0 | ArgStringList &CmdArgs) const { |
199 | 0 | } |
200 | | |
201 | | static void |
202 | | constructHexagonLinkArgs(Compilation &C, const JobAction &JA, |
203 | | const toolchains::HexagonToolChain &HTC, |
204 | | const InputInfo &Output, const InputInfoList &Inputs, |
205 | | const ArgList &Args, ArgStringList &CmdArgs, |
206 | 70 | const char *LinkingOutput) { |
207 | | |
208 | 70 | const Driver &D = HTC.getDriver(); |
209 | | |
210 | | //---------------------------------------------------------------------------- |
211 | | // |
212 | | //---------------------------------------------------------------------------- |
213 | 70 | bool IsStatic = Args.hasArg(options::OPT_static); |
214 | 70 | bool IsShared = Args.hasArg(options::OPT_shared); |
215 | 70 | bool IsPIE = Args.hasArg(options::OPT_pie); |
216 | 70 | bool IncStdLib = !Args.hasArg(options::OPT_nostdlib); |
217 | 70 | bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles); |
218 | 70 | bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); |
219 | 70 | bool UseG0 = false; |
220 | 70 | const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); |
221 | 70 | bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") || |
222 | 62 | llvm::sys::path::stem(Exec).equals_lower("ld.lld")); |
223 | 70 | bool UseShared = IsShared && !IsStatic4 ; |
224 | 70 | StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args); |
225 | | |
226 | | //---------------------------------------------------------------------------- |
227 | | // Silence warnings for various options |
228 | | //---------------------------------------------------------------------------- |
229 | 70 | Args.ClaimAllArgs(options::OPT_g_Group); |
230 | 70 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
231 | 70 | Args.ClaimAllArgs(options::OPT_w); // Other warning options are already |
232 | | // handled somewhere else. |
233 | 70 | Args.ClaimAllArgs(options::OPT_static_libgcc); |
234 | | |
235 | | //---------------------------------------------------------------------------- |
236 | | // |
237 | | //---------------------------------------------------------------------------- |
238 | 70 | if (Args.hasArg(options::OPT_s)) |
239 | 1 | CmdArgs.push_back("-s"); |
240 | | |
241 | 70 | if (Args.hasArg(options::OPT_r)) |
242 | 0 | CmdArgs.push_back("-r"); |
243 | | |
244 | 70 | for (const auto &Opt : HTC.ExtraOpts) |
245 | 0 | CmdArgs.push_back(Opt.c_str()); |
246 | | |
247 | 70 | if (!UseLLD) { |
248 | 62 | CmdArgs.push_back("-march=hexagon"); |
249 | 62 | CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer)); |
250 | 62 | } |
251 | | |
252 | 70 | if (IsShared) { |
253 | 4 | CmdArgs.push_back("-shared"); |
254 | | // The following should be the default, but doing as hexagon-gcc does. |
255 | 4 | CmdArgs.push_back("-call_shared"); |
256 | 4 | } |
257 | | |
258 | 70 | if (IsStatic) |
259 | 2 | CmdArgs.push_back("-static"); |
260 | | |
261 | 70 | if (IsPIE && !IsShared2 ) |
262 | 1 | CmdArgs.push_back("-pie"); |
263 | | |
264 | 70 | if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { |
265 | 9 | CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue()))); |
266 | 9 | UseG0 = G.getValue() == 0; |
267 | 9 | } |
268 | | |
269 | 70 | CmdArgs.push_back("-o"); |
270 | 70 | CmdArgs.push_back(Output.getFilename()); |
271 | | |
272 | 70 | if (HTC.getTriple().isMusl()) { |
273 | 7 | if (!Args.hasArg(options::OPT_shared, options::OPT_static)) |
274 | 6 | CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1"); |
275 | | |
276 | 7 | if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles, |
277 | 7 | options::OPT_nostdlib)) |
278 | 4 | CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o")); |
279 | 3 | else if (Args.hasArg(options::OPT_shared) && |
280 | 1 | !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib)) |
281 | 1 | CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o")); |
282 | | |
283 | 7 | CmdArgs.push_back( |
284 | 7 | Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib")); |
285 | 7 | Args.AddAllArgs(CmdArgs, |
286 | 7 | {options::OPT_T_Group, options::OPT_e, options::OPT_s, |
287 | 7 | options::OPT_t, options::OPT_u_Group}); |
288 | 7 | AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); |
289 | | |
290 | 7 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
291 | 5 | CmdArgs.push_back("-lclang_rt.builtins-hexagon"); |
292 | 5 | CmdArgs.push_back("-lc"); |
293 | 5 | } |
294 | 7 | if (D.CCCIsCXX()) { |
295 | 1 | if (HTC.ShouldLinkCXXStdlib(Args)) |
296 | 1 | HTC.AddCXXStdlibLibArgs(Args, CmdArgs); |
297 | 1 | } |
298 | 7 | return; |
299 | 7 | } |
300 | | |
301 | | //---------------------------------------------------------------------------- |
302 | | // moslib |
303 | | //---------------------------------------------------------------------------- |
304 | 63 | std::vector<std::string> OsLibs; |
305 | 63 | bool HasStandalone = false; |
306 | 5 | for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) { |
307 | 5 | A->claim(); |
308 | 5 | OsLibs.emplace_back(A->getValue()); |
309 | 5 | HasStandalone = HasStandalone || (OsLibs.back() == "standalone"); |
310 | 5 | } |
311 | 63 | if (OsLibs.empty()) { |
312 | 61 | OsLibs.push_back("standalone"); |
313 | 61 | HasStandalone = true; |
314 | 61 | } |
315 | | |
316 | | //---------------------------------------------------------------------------- |
317 | | // Start Files |
318 | | //---------------------------------------------------------------------------- |
319 | 63 | const std::string MCpuSuffix = "/" + CpuVer.str(); |
320 | 63 | const std::string MCpuG0Suffix = MCpuSuffix + "/G0"; |
321 | 63 | const std::string RootDir = |
322 | 63 | HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/"; |
323 | 63 | const std::string StartSubDir = |
324 | 58 | "hexagon/lib" + (UseG0 ? MCpuG0Suffix5 : MCpuSuffix); |
325 | | |
326 | 63 | auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir, |
327 | 237 | const char *Name) -> std::string { |
328 | 237 | std::string RelName = SubDir + Name; |
329 | 237 | std::string P = HTC.GetFilePath(RelName.c_str()); |
330 | 237 | if (llvm::sys::fs::exists(P)) |
331 | 0 | return P; |
332 | 237 | return RootDir + RelName; |
333 | 237 | }; |
334 | | |
335 | 63 | if (IncStdLib && IncStartFiles62 ) { |
336 | 61 | if (!IsShared) { |
337 | 58 | if (HasStandalone) { |
338 | 57 | std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o"); |
339 | 57 | CmdArgs.push_back(Args.MakeArgString(Crt0SA)); |
340 | 57 | } |
341 | 58 | std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o"); |
342 | 58 | CmdArgs.push_back(Args.MakeArgString(Crt0)); |
343 | 58 | } |
344 | 61 | std::string Init = UseShared |
345 | 2 | ? Find(RootDir, StartSubDir + "/pic", "/initS.o") |
346 | 59 | : Find(RootDir, StartSubDir, "/init.o"); |
347 | 61 | CmdArgs.push_back(Args.MakeArgString(Init)); |
348 | 61 | } |
349 | | |
350 | | //---------------------------------------------------------------------------- |
351 | | // Library Search Paths |
352 | | //---------------------------------------------------------------------------- |
353 | 63 | const ToolChain::path_list &LibPaths = HTC.getFilePaths(); |
354 | 63 | for (const auto &LibPath : LibPaths) |
355 | 136 | CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); |
356 | | |
357 | | //---------------------------------------------------------------------------- |
358 | | // |
359 | | //---------------------------------------------------------------------------- |
360 | 63 | Args.AddAllArgs(CmdArgs, |
361 | 63 | {options::OPT_T_Group, options::OPT_e, options::OPT_s, |
362 | 63 | options::OPT_t, options::OPT_u_Group}); |
363 | | |
364 | 63 | AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); |
365 | | |
366 | | //---------------------------------------------------------------------------- |
367 | | // Libraries |
368 | | //---------------------------------------------------------------------------- |
369 | 63 | if (IncStdLib && IncDefLibs62 ) { |
370 | 61 | if (D.CCCIsCXX()) { |
371 | 7 | if (HTC.ShouldLinkCXXStdlib(Args)) |
372 | 7 | HTC.AddCXXStdlibLibArgs(Args, CmdArgs); |
373 | 7 | CmdArgs.push_back("-lm"); |
374 | 7 | } |
375 | | |
376 | 61 | CmdArgs.push_back("--start-group"); |
377 | | |
378 | 61 | if (!IsShared) { |
379 | 58 | for (StringRef Lib : OsLibs) |
380 | 61 | CmdArgs.push_back(Args.MakeArgString("-l" + Lib)); |
381 | 58 | CmdArgs.push_back("-lc"); |
382 | 58 | } |
383 | 61 | CmdArgs.push_back("-lgcc"); |
384 | | |
385 | 61 | CmdArgs.push_back("--end-group"); |
386 | 61 | } |
387 | | |
388 | | //---------------------------------------------------------------------------- |
389 | | // End files |
390 | | //---------------------------------------------------------------------------- |
391 | 63 | if (IncStdLib && IncStartFiles62 ) { |
392 | 61 | std::string Fini = UseShared |
393 | 2 | ? Find(RootDir, StartSubDir + "/pic", "/finiS.o") |
394 | 59 | : Find(RootDir, StartSubDir, "/fini.o"); |
395 | 61 | CmdArgs.push_back(Args.MakeArgString(Fini)); |
396 | 61 | } |
397 | 63 | } |
398 | | |
399 | | void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
400 | | const InputInfo &Output, |
401 | | const InputInfoList &Inputs, |
402 | | const ArgList &Args, |
403 | 70 | const char *LinkingOutput) const { |
404 | 70 | auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); |
405 | | |
406 | 70 | ArgStringList CmdArgs; |
407 | 70 | constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs, |
408 | 70 | LinkingOutput); |
409 | | |
410 | 70 | const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); |
411 | 70 | C.addCommand(std::make_unique<Command>(JA, *this, |
412 | 70 | ResponseFileSupport::AtFileCurCP(), |
413 | 70 | Exec, CmdArgs, Inputs, Output)); |
414 | 70 | } |
415 | | // Hexagon tools end. |
416 | | |
417 | | /// Hexagon Toolchain |
418 | | |
419 | | std::string HexagonToolChain::getHexagonTargetDir( |
420 | | const std::string &InstalledDir, |
421 | 349 | const SmallVectorImpl<std::string> &PrefixDirs) const { |
422 | 349 | std::string InstallRelDir; |
423 | 349 | const Driver &D = getDriver(); |
424 | | |
425 | | // Locate the rest of the toolchain ... |
426 | 349 | for (auto &I : PrefixDirs) |
427 | 0 | if (D.getVFS().exists(I)) |
428 | 0 | return I; |
429 | | |
430 | 349 | if (getVFS().exists(InstallRelDir = InstalledDir + "/../target")) |
431 | 195 | return InstallRelDir; |
432 | | |
433 | 154 | return InstalledDir; |
434 | 154 | } |
435 | | |
436 | | Optional<unsigned> HexagonToolChain::getSmallDataThreshold( |
437 | 267 | const ArgList &Args) { |
438 | 267 | StringRef Gn = ""; |
439 | 267 | if (Arg *A = Args.getLastArg(options::OPT_G)) { |
440 | 12 | Gn = A->getValue(); |
441 | 255 | } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, |
442 | 18 | options::OPT_fPIC)) { |
443 | 18 | Gn = "0"; |
444 | 18 | } |
445 | | |
446 | 267 | unsigned G; |
447 | 267 | if (!Gn.getAsInteger(10, G)) |
448 | 30 | return G; |
449 | | |
450 | 237 | return None; |
451 | 237 | } |
452 | | |
453 | | void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, |
454 | 96 | ToolChain::path_list &LibPaths) const { |
455 | 96 | const Driver &D = getDriver(); |
456 | | |
457 | | //---------------------------------------------------------------------------- |
458 | | // -L Args |
459 | | //---------------------------------------------------------------------------- |
460 | 96 | for (Arg *A : Args.filtered(options::OPT_L)) |
461 | 3 | for (const char *Value : A->getValues()) |
462 | 3 | LibPaths.push_back(Value); |
463 | | |
464 | | //---------------------------------------------------------------------------- |
465 | | // Other standard paths |
466 | | //---------------------------------------------------------------------------- |
467 | 96 | std::vector<std::string> RootDirs; |
468 | 96 | std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), |
469 | 96 | std::back_inserter(RootDirs)); |
470 | | |
471 | 96 | std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
472 | 96 | D.PrefixDirs); |
473 | 96 | if (llvm::find(RootDirs, TargetDir) == RootDirs.end()) |
474 | 96 | RootDirs.push_back(TargetDir); |
475 | | |
476 | 96 | bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC); |
477 | | // Assume G0 with -shared. |
478 | 96 | bool HasG0 = Args.hasArg(options::OPT_shared); |
479 | 96 | if (auto G = getSmallDataThreshold(Args)) |
480 | 9 | HasG0 = G.getValue() == 0; |
481 | | |
482 | 96 | const std::string CpuVer = GetTargetCPUVersion(Args).str(); |
483 | 96 | for (auto &Dir : RootDirs) { |
484 | 96 | std::string LibDir = Dir + "/hexagon/lib"; |
485 | 96 | std::string LibDirCpu = LibDir + '/' + CpuVer; |
486 | 96 | if (HasG0) { |
487 | 6 | if (HasPIC) |
488 | 2 | LibPaths.push_back(LibDirCpu + "/G0/pic"); |
489 | 6 | LibPaths.push_back(LibDirCpu + "/G0"); |
490 | 6 | } |
491 | 96 | LibPaths.push_back(LibDirCpu); |
492 | 96 | LibPaths.push_back(LibDir); |
493 | 96 | } |
494 | 96 | } |
495 | | |
496 | | HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple, |
497 | | const llvm::opt::ArgList &Args) |
498 | 96 | : Linux(D, Triple, Args) { |
499 | 96 | const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
500 | 96 | D.PrefixDirs); |
501 | | |
502 | | // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to |
503 | | // program paths |
504 | 96 | const std::string BinDir(TargetDir + "/bin"); |
505 | 96 | if (D.getVFS().exists(BinDir)) |
506 | 0 | getProgramPaths().push_back(BinDir); |
507 | | |
508 | 96 | ToolChain::path_list &LibPaths = getFilePaths(); |
509 | | |
510 | | // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets |
511 | | // 'elf' OS type, so the Linux paths are not appropriate. When we actually |
512 | | // support 'linux' we'll need to fix this up |
513 | 96 | LibPaths.clear(); |
514 | 96 | getHexagonLibraryPaths(Args, LibPaths); |
515 | 96 | } |
516 | | |
517 | 96 | HexagonToolChain::~HexagonToolChain() {} |
518 | | |
519 | | void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args, |
520 | 8 | ArgStringList &CmdArgs) const { |
521 | 8 | CXXStdlibType Type = GetCXXStdlibType(Args); |
522 | 8 | switch (Type) { |
523 | 2 | case ToolChain::CST_Libcxx: |
524 | 2 | CmdArgs.push_back("-lc++"); |
525 | 2 | CmdArgs.push_back("-lc++abi"); |
526 | 2 | CmdArgs.push_back("-lunwind"); |
527 | 2 | break; |
528 | | |
529 | 6 | case ToolChain::CST_Libstdcxx: |
530 | 6 | CmdArgs.push_back("-lstdc++"); |
531 | 6 | break; |
532 | 8 | } |
533 | 8 | } |
534 | | |
535 | 5 | Tool *HexagonToolChain::buildAssembler() const { |
536 | 5 | return new tools::hexagon::Assembler(*this); |
537 | 5 | } |
538 | | |
539 | 70 | Tool *HexagonToolChain::buildLinker() const { |
540 | 70 | return new tools::hexagon::Linker(*this); |
541 | 70 | } |
542 | | |
543 | | unsigned HexagonToolChain::getOptimizationLevel( |
544 | 0 | const llvm::opt::ArgList &DriverArgs) const { |
545 | | // Copied in large part from lib/Frontend/CompilerInvocation.cpp. |
546 | 0 | Arg *A = DriverArgs.getLastArg(options::OPT_O_Group); |
547 | 0 | if (!A) |
548 | 0 | return 0; |
549 | | |
550 | 0 | if (A->getOption().matches(options::OPT_O0)) |
551 | 0 | return 0; |
552 | 0 | if (A->getOption().matches(options::OPT_Ofast) || |
553 | 0 | A->getOption().matches(options::OPT_O4)) |
554 | 0 | return 3; |
555 | 0 | assert(A->getNumValues() != 0); |
556 | 0 | StringRef S(A->getValue()); |
557 | 0 | if (S == "s" || S == "z" || S.empty()) |
558 | 0 | return 2; |
559 | 0 | if (S == "g") |
560 | 0 | return 1; |
561 | | |
562 | 0 | unsigned OptLevel; |
563 | 0 | if (S.getAsInteger(10, OptLevel)) |
564 | 0 | return 0; |
565 | 0 | return OptLevel; |
566 | 0 | } |
567 | | |
568 | | void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs, |
569 | | ArgStringList &CC1Args, |
570 | 97 | Action::OffloadKind) const { |
571 | | |
572 | 97 | bool UseInitArrayDefault = getTriple().isMusl(); |
573 | | |
574 | 97 | if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, |
575 | 97 | options::OPT_fno_use_init_array, |
576 | 97 | UseInitArrayDefault)) |
577 | 90 | CC1Args.push_back("-fno-use-init-array"); |
578 | | |
579 | 97 | if (DriverArgs.hasArg(options::OPT_ffixed_r19)) { |
580 | 3 | CC1Args.push_back("-target-feature"); |
581 | 3 | CC1Args.push_back("+reserved-r19"); |
582 | 3 | } |
583 | 97 | if (isAutoHVXEnabled(DriverArgs)) { |
584 | 2 | CC1Args.push_back("-mllvm"); |
585 | 2 | CC1Args.push_back("-hexagon-autohvx"); |
586 | 2 | } |
587 | 97 | } |
588 | | |
589 | | void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
590 | 96 | ArgStringList &CC1Args) const { |
591 | 96 | if (DriverArgs.hasArg(options::OPT_nostdinc) || |
592 | 95 | DriverArgs.hasArg(options::OPT_nostdlibinc)) |
593 | 3 | return; |
594 | | |
595 | 93 | const Driver &D = getDriver(); |
596 | 93 | if (!D.SysRoot.empty()) { |
597 | 7 | SmallString<128> P(D.SysRoot); |
598 | 7 | if (getTriple().isMusl()) |
599 | 6 | llvm::sys::path::append(P, "usr/include"); |
600 | 1 | else |
601 | 1 | llvm::sys::path::append(P, "include"); |
602 | 7 | addExternCSystemInclude(DriverArgs, CC1Args, P.str()); |
603 | 7 | return; |
604 | 7 | } |
605 | | |
606 | 86 | std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
607 | 86 | D.PrefixDirs); |
608 | 86 | addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include"); |
609 | 86 | } |
610 | | |
611 | | void HexagonToolChain::addLibCxxIncludePaths( |
612 | | const llvm::opt::ArgList &DriverArgs, |
613 | 2 | llvm::opt::ArgStringList &CC1Args) const { |
614 | 2 | const Driver &D = getDriver(); |
615 | 2 | if (!D.SysRoot.empty() && getTriple().isMusl()1 ) |
616 | 1 | addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "", |
617 | 1 | "", DriverArgs, CC1Args); |
618 | 1 | else if (getTriple().isMusl()) |
619 | 0 | addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "", |
620 | 0 | DriverArgs, CC1Args); |
621 | 1 | else { |
622 | 1 | std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); |
623 | 1 | addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "", |
624 | 1 | "", DriverArgs, CC1Args); |
625 | 1 | } |
626 | 2 | } |
627 | | void HexagonToolChain::addLibStdCxxIncludePaths( |
628 | | const llvm::opt::ArgList &DriverArgs, |
629 | 7 | llvm::opt::ArgStringList &CC1Args) const { |
630 | 7 | const Driver &D = getDriver(); |
631 | 7 | std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); |
632 | 7 | addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "", |
633 | 7 | DriverArgs, CC1Args); |
634 | 7 | } |
635 | | |
636 | | ToolChain::CXXStdlibType |
637 | 17 | HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const { |
638 | 17 | Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); |
639 | 17 | if (!A) { |
640 | 15 | if (getTriple().isMusl()) |
641 | 2 | return ToolChain::CST_Libcxx; |
642 | 13 | else |
643 | 13 | return ToolChain::CST_Libstdcxx; |
644 | 2 | } |
645 | 2 | StringRef Value = A->getValue(); |
646 | 2 | if (Value != "libstdc++" && Value != "libc++") |
647 | 0 | getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); |
648 | | |
649 | 2 | if (Value == "libstdc++") |
650 | 0 | return ToolChain::CST_Libstdcxx; |
651 | 2 | else if (Value == "libc++") |
652 | 2 | return ToolChain::CST_Libcxx; |
653 | 0 | else |
654 | 0 | return ToolChain::CST_Libstdcxx; |
655 | 2 | } |
656 | | |
657 | 193 | bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) { |
658 | 193 | if (Arg *A = Args.getLastArg(options::OPT_fvectorize, |
659 | 6 | options::OPT_fno_vectorize)) |
660 | 6 | return A->getOption().matches(options::OPT_fvectorize); |
661 | 187 | return false; |
662 | 187 | } |
663 | | |
664 | | // |
665 | | // Returns the default CPU for Hexagon. This is the default compilation target |
666 | | // if no Hexagon processor is selected at the command-line. |
667 | | // |
668 | 123 | const StringRef HexagonToolChain::GetDefaultCPU() { |
669 | 123 | return "hexagonv60"; |
670 | 123 | } |
671 | | |
672 | 363 | const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) { |
673 | 363 | Arg *CpuArg = nullptr; |
674 | 363 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) |
675 | 240 | CpuArg = A; |
676 | | |
677 | 240 | StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU()123 ; |
678 | 363 | if (CPU.startswith("hexagon")) |
679 | 363 | return CPU.substr(sizeof("hexagon") - 1); |
680 | 0 | return CPU; |
681 | 0 | } |