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