1 //===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 #include "CommonArgs.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/DriverDiagnostic.h"
14 #include "clang/Driver/InputInfo.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"
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
;
28 // Default hvx-length for various versions.
29 static StringRef
getDefaultHvxLength(StringRef HvxVer
) {
30 return llvm::StringSwitch
<StringRef
>(HvxVer
)
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_insensitive("64b") && !Val
.equals_insensitive("128b"))
42 D
.Diag(diag::err_drv_unsupported_option_argument
)
43 << A
->getOption().getName() << Val
;
47 // Handle hvx target features explicitly.
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
);
54 auto makeFeature
= [&Args
](Twine T
, bool Enable
) -> StringRef
{
55 const std::string
&S
= T
.str();
57 if (Opt
.endswith("="))
58 Opt
= Opt
.drop_back(1);
59 if (Opt
.startswith("mno-"))
60 Opt
= Opt
.drop_front(4);
61 else if (Opt
.startswith("m"))
62 Opt
= Opt
.drop_front(1);
63 return Args
.MakeArgString(Twine(Enable
? "+" : "-") + Twine(Opt
));
66 auto withMinus
= [](StringRef S
) -> std::string
{
70 // Drop tiny core suffix for HVX version.
72 (Cpu
.back() == 'T' || Cpu
.back() == 't' ? Cpu
.drop_back(1) : Cpu
).str();
75 // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags
76 // are both present, the last one wins.
78 Args
.getLastArg(options::OPT_mhexagon_hvx
, options::OPT_mhexagon_hvx_EQ
,
79 options::OPT_mno_hexagon_hvx
);
81 if (HvxEnablingArg
->getOption().matches(options::OPT_mno_hexagon_hvx
))
82 HvxEnablingArg
= nullptr;
86 // If -mhvx[=] was given, it takes precedence.
87 if (Arg
*A
= Args
.getLastArg(options::OPT_mhexagon_hvx
,
88 options::OPT_mhexagon_hvx_EQ
)) {
89 // If the version was given, set HvxVer. Otherwise HvxVer
90 // will remain equal to the CPU version.
91 if (A
->getOption().matches(options::OPT_mhexagon_hvx_EQ
))
92 HvxVer
= StringRef(A
->getValue()).lower();
95 Features
.push_back(makeFeature(Twine("hvx") + HvxVer
, true));
96 } else if (Arg
*A
= Args
.getLastArg(options::OPT_mno_hexagon_hvx
)) {
97 // If there was an explicit -mno-hvx, add -hvx to target features.
98 Features
.push_back(makeFeature(A
->getOption().getName(), false));
101 StringRef HvxLen
= getDefaultHvxLength(HvxVer
);
103 // Handle -mhvx-length=.
104 if (Arg
*A
= Args
.getLastArg(options::OPT_mhexagon_hvx_length_EQ
)) {
105 // These flags are valid only if HVX in enabled.
107 D
.Diag(diag::err_drv_needs_hvx
) << withMinus(A
->getOption().getName());
108 else if (A
->getOption().matches(options::OPT_mhexagon_hvx_length_EQ
))
109 HvxLen
= A
->getValue();
113 StringRef L
= makeFeature(Twine("hvx-length") + HvxLen
.lower(), true);
114 Features
.push_back(L
);
118 // getAsInteger returns 'true' on error.
119 if (StringRef(HvxVer
).drop_front(1).getAsInteger(10, HvxVerNum
))
122 // Handle HVX floating point flags.
123 auto checkFlagHvxVersion
= [&](auto FlagOn
, auto FlagOff
,
124 unsigned MinVerNum
) -> Optional
<StringRef
> {
125 // Return an Optional<StringRef>:
126 // - None indicates a verification failure, or that the flag was not
128 // - Otherwise the returned value is that name of the feature to add
130 Arg
*A
= Args
.getLastArg(FlagOn
, FlagOff
);
134 StringRef OptName
= A
->getOption().getName();
135 if (A
->getOption().matches(FlagOff
))
136 return makeFeature(OptName
, false);
139 D
.Diag(diag::err_drv_needs_hvx
) << withMinus(OptName
);
142 if (HvxVerNum
< MinVerNum
) {
143 D
.Diag(diag::err_drv_needs_hvx_version
)
144 << withMinus(OptName
) << ("v" + std::to_string(HvxVerNum
));
147 return makeFeature(OptName
, true);
150 if (auto F
= checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat
,
151 options::OPT_mno_hexagon_hvx_qfloat
, 68)) {
152 Features
.push_back(*F
);
154 if (auto F
= checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp
,
155 options::OPT_mno_hexagon_hvx_ieee_fp
, 68)) {
156 Features
.push_back(*F
);
160 // Hexagon target features.
161 void hexagon::getHexagonTargetFeatures(const Driver
&D
, const ArgList
&Args
,
162 std::vector
<StringRef
> &Features
) {
163 handleTargetFeaturesGroup(Args
, Features
,
164 options::OPT_m_hexagon_Features_Group
);
166 bool UseLongCalls
= false;
167 if (Arg
*A
= Args
.getLastArg(options::OPT_mlong_calls
,
168 options::OPT_mno_long_calls
)) {
169 if (A
->getOption().matches(options::OPT_mlong_calls
))
173 Features
.push_back(UseLongCalls
? "+long-calls" : "-long-calls");
176 StringRef
Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args
));
177 // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
178 // have no dependency on micro-architecture.
179 const bool TinyCore
= Cpu
.contains('t');
182 Cpu
= Cpu
.take_front(Cpu
.size() - 1);
184 handleHVXTargetFeatures(D
, Args
, Features
, Cpu
, HasHVX
);
186 if (HexagonToolChain::isAutoHVXEnabled(Args
) && !HasHVX
)
187 D
.Diag(diag::warn_drv_needs_hvx
) << "auto-vectorization";
190 // Hexagon tools start.
191 void hexagon::Assembler::RenderExtraToolArgs(const JobAction
&JA
,
192 ArgStringList
&CmdArgs
) const {
195 void hexagon::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
196 const InputInfo
&Output
,
197 const InputInfoList
&Inputs
,
199 const char *LinkingOutput
) const {
200 claimNoWarnArgs(Args
);
202 auto &HTC
= static_cast<const toolchains::HexagonToolChain
&>(getToolChain());
203 const Driver
&D
= HTC
.getDriver();
204 ArgStringList CmdArgs
;
206 CmdArgs
.push_back("--arch=hexagon");
208 RenderExtraToolArgs(JA
, CmdArgs
);
210 const char *AsName
= "llvm-mc";
211 CmdArgs
.push_back("-filetype=obj");
212 CmdArgs
.push_back(Args
.MakeArgString(
214 toolchains::HexagonToolChain::GetTargetCPUVersion(Args
)));
216 addSanitizerRuntimes(HTC
, Args
, CmdArgs
);
218 if (Output
.isFilename()) {
219 CmdArgs
.push_back("-o");
220 CmdArgs
.push_back(Output
.getFilename());
222 assert(Output
.isNothing() && "Unexpected output");
223 CmdArgs
.push_back("-fsyntax-only");
226 if (Arg
*A
= Args
.getLastArg(options::OPT_mhexagon_hvx_ieee_fp
,
227 options::OPT_mno_hexagon_hvx_ieee_fp
)) {
228 if (A
->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp
))
229 CmdArgs
.push_back("-mhvx-ieee-fp");
232 if (auto G
= toolchains::HexagonToolChain::getSmallDataThreshold(Args
)) {
233 CmdArgs
.push_back(Args
.MakeArgString("-gpsize=" + Twine(*G
)));
236 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
238 // Only pass -x if gcc will understand it; otherwise hope gcc
239 // understands the suffix correctly. The main use case this would go
240 // wrong in is for linker inputs if they happened to have an odd
241 // suffix; really the only way to get this to happen is a command
242 // like '-x foobar a.c' which will treat a.c like a linker input.
244 // FIXME: For the linker case specifically, can we safely convert
245 // inputs into '-Wl,' options?
246 for (const auto &II
: Inputs
) {
247 // Don't try to pass LLVM or AST inputs to a generic gcc.
248 if (types::isLLVMIR(II
.getType()))
249 D
.Diag(clang::diag::err_drv_no_linker_llvm_support
)
250 << HTC
.getTripleString();
251 else if (II
.getType() == types::TY_AST
)
252 D
.Diag(clang::diag::err_drv_no_ast_support
)
253 << HTC
.getTripleString();
254 else if (II
.getType() == types::TY_ModuleFile
)
255 D
.Diag(diag::err_drv_no_module_support
)
256 << HTC
.getTripleString();
259 CmdArgs
.push_back(II
.getFilename());
261 // Don't render as input, we need gcc to do the translations.
262 // FIXME: What is this?
263 II
.getInputArg().render(Args
, CmdArgs
);
266 auto *Exec
= Args
.MakeArgString(HTC
.GetProgramPath(AsName
));
267 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
268 ResponseFileSupport::AtFileCurCP(),
269 Exec
, CmdArgs
, Inputs
, Output
));
272 void hexagon::Linker::RenderExtraToolArgs(const JobAction
&JA
,
273 ArgStringList
&CmdArgs
) const {
277 constructHexagonLinkArgs(Compilation
&C
, const JobAction
&JA
,
278 const toolchains::HexagonToolChain
&HTC
,
279 const InputInfo
&Output
, const InputInfoList
&Inputs
,
280 const ArgList
&Args
, ArgStringList
&CmdArgs
,
281 const char *LinkingOutput
) {
283 const Driver
&D
= HTC
.getDriver();
285 //----------------------------------------------------------------------------
287 //----------------------------------------------------------------------------
288 bool IsStatic
= Args
.hasArg(options::OPT_static
);
289 bool IsShared
= Args
.hasArg(options::OPT_shared
);
290 bool IsPIE
= Args
.hasArg(options::OPT_pie
);
291 bool IncStdLib
= !Args
.hasArg(options::OPT_nostdlib
);
292 bool IncStartFiles
= !Args
.hasArg(options::OPT_nostartfiles
);
293 bool IncDefLibs
= !Args
.hasArg(options::OPT_nodefaultlibs
);
295 const char *Exec
= Args
.MakeArgString(HTC
.GetLinkerPath());
296 bool UseLLD
= (llvm::sys::path::filename(Exec
).equals_insensitive("ld.lld") ||
297 llvm::sys::path::stem(Exec
).equals_insensitive("ld.lld"));
298 bool UseShared
= IsShared
&& !IsStatic
;
299 StringRef CpuVer
= toolchains::HexagonToolChain::GetTargetCPUVersion(Args
);
301 bool NeedsSanitizerDeps
= addSanitizerRuntimes(HTC
, Args
, CmdArgs
);
302 bool NeedsXRayDeps
= addXRayRuntime(HTC
, Args
, CmdArgs
);
304 //----------------------------------------------------------------------------
305 // Silence warnings for various options
306 //----------------------------------------------------------------------------
307 Args
.ClaimAllArgs(options::OPT_g_Group
);
308 Args
.ClaimAllArgs(options::OPT_emit_llvm
);
309 Args
.ClaimAllArgs(options::OPT_w
); // Other warning options are already
310 // handled somewhere else.
311 Args
.ClaimAllArgs(options::OPT_static_libgcc
);
313 //----------------------------------------------------------------------------
315 //----------------------------------------------------------------------------
316 if (Args
.hasArg(options::OPT_s
))
317 CmdArgs
.push_back("-s");
319 if (Args
.hasArg(options::OPT_r
))
320 CmdArgs
.push_back("-r");
322 for (const auto &Opt
: HTC
.ExtraOpts
)
323 CmdArgs
.push_back(Opt
.c_str());
326 CmdArgs
.push_back("-march=hexagon");
327 CmdArgs
.push_back(Args
.MakeArgString("-mcpu=hexagon" + CpuVer
));
331 CmdArgs
.push_back("-shared");
332 // The following should be the default, but doing as hexagon-gcc does.
333 CmdArgs
.push_back("-call_shared");
337 CmdArgs
.push_back("-static");
339 if (IsPIE
&& !IsShared
)
340 CmdArgs
.push_back("-pie");
342 if (auto G
= toolchains::HexagonToolChain::getSmallDataThreshold(Args
)) {
343 CmdArgs
.push_back(Args
.MakeArgString("-G" + Twine(G
.value())));
344 UseG0
= G
.value() == 0;
347 CmdArgs
.push_back("-o");
348 CmdArgs
.push_back(Output
.getFilename());
350 if (HTC
.getTriple().isMusl()) {
351 if (!Args
.hasArg(options::OPT_shared
, options::OPT_static
))
352 CmdArgs
.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
354 if (!Args
.hasArg(options::OPT_shared
, options::OPT_nostartfiles
,
355 options::OPT_nostdlib
))
356 CmdArgs
.push_back(Args
.MakeArgString(D
.SysRoot
+ "/usr/lib/crt1.o"));
357 else if (Args
.hasArg(options::OPT_shared
) &&
358 !Args
.hasArg(options::OPT_nostartfiles
, options::OPT_nostdlib
))
359 CmdArgs
.push_back(Args
.MakeArgString(D
.SysRoot
+ "/usr/lib/crti.o"));
362 Args
.MakeArgString(StringRef("-L") + D
.SysRoot
+ "/usr/lib"));
363 Args
.AddAllArgs(CmdArgs
,
364 {options::OPT_T_Group
, options::OPT_e
, options::OPT_s
,
365 options::OPT_t
, options::OPT_u_Group
});
366 AddLinkerInputs(HTC
, Inputs
, Args
, CmdArgs
, JA
);
368 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
)) {
369 if (NeedsSanitizerDeps
) {
370 linkSanitizerRuntimeDeps(HTC
, CmdArgs
);
372 CmdArgs
.push_back("-lunwind");
375 linkXRayRuntimeDeps(HTC
, CmdArgs
);
377 CmdArgs
.push_back("-lclang_rt.builtins-hexagon");
378 CmdArgs
.push_back("-lc");
381 if (HTC
.ShouldLinkCXXStdlib(Args
))
382 HTC
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
387 //----------------------------------------------------------------------------
389 //----------------------------------------------------------------------------
390 std::vector
<std::string
> OsLibs
;
391 bool HasStandalone
= false;
392 for (const Arg
*A
: Args
.filtered(options::OPT_moslib_EQ
)) {
394 OsLibs
.emplace_back(A
->getValue());
395 HasStandalone
= HasStandalone
|| (OsLibs
.back() == "standalone");
397 if (OsLibs
.empty()) {
398 OsLibs
.push_back("standalone");
399 HasStandalone
= true;
402 //----------------------------------------------------------------------------
404 //----------------------------------------------------------------------------
405 const std::string MCpuSuffix
= "/" + CpuVer
.str();
406 const std::string MCpuG0Suffix
= MCpuSuffix
+ "/G0";
407 const std::string RootDir
=
408 HTC
.getHexagonTargetDir(D
.InstalledDir
, D
.PrefixDirs
) + "/";
409 const std::string StartSubDir
=
410 "hexagon/lib" + (UseG0
? MCpuG0Suffix
: MCpuSuffix
);
412 auto Find
= [&HTC
] (const std::string
&RootDir
, const std::string
&SubDir
,
413 const char *Name
) -> std::string
{
414 std::string RelName
= SubDir
+ Name
;
415 std::string P
= HTC
.GetFilePath(RelName
.c_str());
416 if (llvm::sys::fs::exists(P
))
418 return RootDir
+ RelName
;
421 if (IncStdLib
&& IncStartFiles
) {
424 std::string Crt0SA
= Find(RootDir
, StartSubDir
, "/crt0_standalone.o");
425 CmdArgs
.push_back(Args
.MakeArgString(Crt0SA
));
427 std::string Crt0
= Find(RootDir
, StartSubDir
, "/crt0.o");
428 CmdArgs
.push_back(Args
.MakeArgString(Crt0
));
430 std::string Init
= UseShared
431 ? Find(RootDir
, StartSubDir
+ "/pic", "/initS.o")
432 : Find(RootDir
, StartSubDir
, "/init.o");
433 CmdArgs
.push_back(Args
.MakeArgString(Init
));
436 //----------------------------------------------------------------------------
437 // Library Search Paths
438 //----------------------------------------------------------------------------
439 const ToolChain::path_list
&LibPaths
= HTC
.getFilePaths();
440 for (const auto &LibPath
: LibPaths
)
441 CmdArgs
.push_back(Args
.MakeArgString(StringRef("-L") + LibPath
));
443 //----------------------------------------------------------------------------
445 //----------------------------------------------------------------------------
446 Args
.AddAllArgs(CmdArgs
,
447 {options::OPT_T_Group
, options::OPT_e
, options::OPT_s
,
448 options::OPT_t
, options::OPT_u_Group
});
450 AddLinkerInputs(HTC
, Inputs
, Args
, CmdArgs
, JA
);
452 //----------------------------------------------------------------------------
454 //----------------------------------------------------------------------------
455 if (IncStdLib
&& IncDefLibs
) {
457 if (HTC
.ShouldLinkCXXStdlib(Args
))
458 HTC
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
459 CmdArgs
.push_back("-lm");
462 CmdArgs
.push_back("--start-group");
465 for (StringRef Lib
: OsLibs
)
466 CmdArgs
.push_back(Args
.MakeArgString("-l" + Lib
));
467 CmdArgs
.push_back("-lc");
469 CmdArgs
.push_back("-lgcc");
471 CmdArgs
.push_back("--end-group");
474 //----------------------------------------------------------------------------
476 //----------------------------------------------------------------------------
477 if (IncStdLib
&& IncStartFiles
) {
478 std::string Fini
= UseShared
479 ? Find(RootDir
, StartSubDir
+ "/pic", "/finiS.o")
480 : Find(RootDir
, StartSubDir
, "/fini.o");
481 CmdArgs
.push_back(Args
.MakeArgString(Fini
));
485 void hexagon::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
486 const InputInfo
&Output
,
487 const InputInfoList
&Inputs
,
489 const char *LinkingOutput
) const {
490 auto &HTC
= static_cast<const toolchains::HexagonToolChain
&>(getToolChain());
492 ArgStringList CmdArgs
;
493 constructHexagonLinkArgs(C
, JA
, HTC
, Output
, Inputs
, Args
, CmdArgs
,
496 const char *Exec
= Args
.MakeArgString(HTC
.GetLinkerPath());
497 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
498 ResponseFileSupport::AtFileCurCP(),
499 Exec
, CmdArgs
, Inputs
, Output
));
501 // Hexagon tools end.
503 /// Hexagon Toolchain
505 std::string
HexagonToolChain::getHexagonTargetDir(
506 const std::string
&InstalledDir
,
507 const SmallVectorImpl
<std::string
> &PrefixDirs
) const {
508 std::string InstallRelDir
;
509 const Driver
&D
= getDriver();
511 // Locate the rest of the toolchain ...
512 for (auto &I
: PrefixDirs
)
513 if (D
.getVFS().exists(I
))
516 if (getVFS().exists(InstallRelDir
= InstalledDir
+ "/../target"))
517 return InstallRelDir
;
522 Optional
<unsigned> HexagonToolChain::getSmallDataThreshold(
523 const ArgList
&Args
) {
525 if (Arg
*A
= Args
.getLastArg(options::OPT_G
)) {
527 } else if (Args
.getLastArg(options::OPT_shared
, options::OPT_fpic
,
528 options::OPT_fPIC
)) {
533 if (!Gn
.getAsInteger(10, G
))
539 std::string
HexagonToolChain::getCompilerRTPath() const {
540 SmallString
<128> Dir(getDriver().SysRoot
);
541 llvm::sys::path::append(Dir
, "usr", "lib");
542 Dir
+= SelectedMultilib
.gccSuffix();
543 return std::string(Dir
.str());
546 void HexagonToolChain::getHexagonLibraryPaths(const ArgList
&Args
,
547 ToolChain::path_list
&LibPaths
) const {
548 const Driver
&D
= getDriver();
550 //----------------------------------------------------------------------------
552 //----------------------------------------------------------------------------
553 for (Arg
*A
: Args
.filtered(options::OPT_L
))
554 llvm::append_range(LibPaths
, A
->getValues());
556 //----------------------------------------------------------------------------
557 // Other standard paths
558 //----------------------------------------------------------------------------
559 std::vector
<std::string
> RootDirs
;
560 std::copy(D
.PrefixDirs
.begin(), D
.PrefixDirs
.end(),
561 std::back_inserter(RootDirs
));
563 std::string TargetDir
= getHexagonTargetDir(D
.getInstalledDir(),
565 if (!llvm::is_contained(RootDirs
, TargetDir
))
566 RootDirs
.push_back(TargetDir
);
568 bool HasPIC
= Args
.hasArg(options::OPT_fpic
, options::OPT_fPIC
);
569 // Assume G0 with -shared.
570 bool HasG0
= Args
.hasArg(options::OPT_shared
);
571 if (auto G
= getSmallDataThreshold(Args
))
574 const std::string CpuVer
= GetTargetCPUVersion(Args
).str();
575 for (auto &Dir
: RootDirs
) {
576 std::string LibDir
= Dir
+ "/hexagon/lib";
577 std::string LibDirCpu
= LibDir
+ '/' + CpuVer
;
580 LibPaths
.push_back(LibDirCpu
+ "/G0/pic");
581 LibPaths
.push_back(LibDirCpu
+ "/G0");
583 LibPaths
.push_back(LibDirCpu
);
584 LibPaths
.push_back(LibDir
);
588 HexagonToolChain::HexagonToolChain(const Driver
&D
, const llvm::Triple
&Triple
,
589 const llvm::opt::ArgList
&Args
)
590 : Linux(D
, Triple
, Args
) {
591 const std::string TargetDir
= getHexagonTargetDir(D
.getInstalledDir(),
594 // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
596 const std::string
BinDir(TargetDir
+ "/bin");
597 if (D
.getVFS().exists(BinDir
))
598 getProgramPaths().push_back(BinDir
);
600 ToolChain::path_list
&LibPaths
= getFilePaths();
602 // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
603 // 'elf' OS type, so the Linux paths are not appropriate. When we actually
604 // support 'linux' we'll need to fix this up
606 getHexagonLibraryPaths(Args
, LibPaths
);
609 HexagonToolChain::~HexagonToolChain() {}
611 void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList
&Args
,
612 ArgStringList
&CmdArgs
) const {
613 CXXStdlibType Type
= GetCXXStdlibType(Args
);
615 case ToolChain::CST_Libcxx
:
616 CmdArgs
.push_back("-lc++");
617 if (Args
.hasArg(options::OPT_fexperimental_library
))
618 CmdArgs
.push_back("-lc++experimental");
619 CmdArgs
.push_back("-lc++abi");
620 CmdArgs
.push_back("-lunwind");
623 case ToolChain::CST_Libstdcxx
:
624 CmdArgs
.push_back("-lstdc++");
629 Tool
*HexagonToolChain::buildAssembler() const {
630 return new tools::hexagon::Assembler(*this);
633 Tool
*HexagonToolChain::buildLinker() const {
634 return new tools::hexagon::Linker(*this);
637 unsigned HexagonToolChain::getOptimizationLevel(
638 const llvm::opt::ArgList
&DriverArgs
) const {
639 // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
640 Arg
*A
= DriverArgs
.getLastArg(options::OPT_O_Group
);
644 if (A
->getOption().matches(options::OPT_O0
))
646 if (A
->getOption().matches(options::OPT_Ofast
) ||
647 A
->getOption().matches(options::OPT_O4
))
649 assert(A
->getNumValues() != 0);
650 StringRef
S(A
->getValue());
651 if (S
== "s" || S
== "z" || S
.empty())
657 if (S
.getAsInteger(10, OptLevel
))
662 void HexagonToolChain::addClangTargetOptions(const ArgList
&DriverArgs
,
663 ArgStringList
&CC1Args
,
664 Action::OffloadKind
) const {
666 bool UseInitArrayDefault
= getTriple().isMusl();
668 if (!DriverArgs
.hasFlag(options::OPT_fuse_init_array
,
669 options::OPT_fno_use_init_array
,
670 UseInitArrayDefault
))
671 CC1Args
.push_back("-fno-use-init-array");
673 if (DriverArgs
.hasArg(options::OPT_ffixed_r19
)) {
674 CC1Args
.push_back("-target-feature");
675 CC1Args
.push_back("+reserved-r19");
677 if (isAutoHVXEnabled(DriverArgs
)) {
678 CC1Args
.push_back("-mllvm");
679 CC1Args
.push_back("-hexagon-autohvx");
683 void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList
&DriverArgs
,
684 ArgStringList
&CC1Args
) const {
685 if (DriverArgs
.hasArg(options::OPT_nostdinc
))
688 const bool IsELF
= !getTriple().isMusl() && !getTriple().isOSLinux();
689 const bool IsLinuxMusl
= getTriple().isMusl() && getTriple().isOSLinux();
691 const Driver
&D
= getDriver();
692 SmallString
<128> ResourceDirInclude(D
.ResourceDir
);
694 llvm::sys::path::append(ResourceDirInclude
, "include");
695 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
) &&
696 (!IsLinuxMusl
|| DriverArgs
.hasArg(options::OPT_nostdlibinc
)))
697 addSystemInclude(DriverArgs
, CC1Args
, ResourceDirInclude
);
699 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
))
702 const bool HasSysRoot
= !D
.SysRoot
.empty();
704 SmallString
<128> P(D
.SysRoot
);
706 llvm::sys::path::append(P
, "usr/include");
708 llvm::sys::path::append(P
, "include");
710 addExternCSystemInclude(DriverArgs
, CC1Args
, P
.str());
712 addSystemInclude(DriverArgs
, CC1Args
, P
+ "/usr/local/include");
714 AddMultilibIncludeArgs(DriverArgs
, CC1Args
);
717 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
) && IsLinuxMusl
)
718 addSystemInclude(DriverArgs
, CC1Args
, ResourceDirInclude
);
722 std::string TargetDir
= getHexagonTargetDir(D
.getInstalledDir(),
724 addExternCSystemInclude(DriverArgs
, CC1Args
, TargetDir
+ "/hexagon/include");
727 void HexagonToolChain::addLibCxxIncludePaths(
728 const llvm::opt::ArgList
&DriverArgs
,
729 llvm::opt::ArgStringList
&CC1Args
) const {
730 const Driver
&D
= getDriver();
731 if (!D
.SysRoot
.empty() && getTriple().isMusl())
732 addLibStdCXXIncludePaths(D
.SysRoot
+ "/usr/include/c++/v1", "", "",
733 DriverArgs
, CC1Args
);
734 else if (getTriple().isMusl())
735 addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs
,
738 std::string TargetDir
= getHexagonTargetDir(D
.InstalledDir
, D
.PrefixDirs
);
739 addLibStdCXXIncludePaths(TargetDir
+ "/hexagon/include/c++/v1", "", "",
740 DriverArgs
, CC1Args
);
743 void HexagonToolChain::addLibStdCxxIncludePaths(
744 const llvm::opt::ArgList
&DriverArgs
,
745 llvm::opt::ArgStringList
&CC1Args
) const {
746 const Driver
&D
= getDriver();
747 std::string TargetDir
= getHexagonTargetDir(D
.InstalledDir
, D
.PrefixDirs
);
748 addLibStdCXXIncludePaths(TargetDir
+ "/hexagon/include/c++", "", "",
749 DriverArgs
, CC1Args
);
752 ToolChain::CXXStdlibType
753 HexagonToolChain::GetCXXStdlibType(const ArgList
&Args
) const {
754 Arg
*A
= Args
.getLastArg(options::OPT_stdlib_EQ
);
756 if (getTriple().isMusl())
757 return ToolChain::CST_Libcxx
;
759 return ToolChain::CST_Libstdcxx
;
761 StringRef Value
= A
->getValue();
762 if (Value
!= "libstdc++" && Value
!= "libc++")
763 getDriver().Diag(diag::err_drv_invalid_stdlib_name
) << A
->getAsString(Args
);
765 if (Value
== "libstdc++")
766 return ToolChain::CST_Libstdcxx
;
767 else if (Value
== "libc++")
768 return ToolChain::CST_Libcxx
;
770 return ToolChain::CST_Libstdcxx
;
773 bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList
&Args
) {
774 if (Arg
*A
= Args
.getLastArg(options::OPT_fvectorize
,
775 options::OPT_fno_vectorize
))
776 return A
->getOption().matches(options::OPT_fvectorize
);
781 // Returns the default CPU for Hexagon. This is the default compilation target
782 // if no Hexagon processor is selected at the command-line.
784 StringRef
HexagonToolChain::GetDefaultCPU() {
788 StringRef
HexagonToolChain::GetTargetCPUVersion(const ArgList
&Args
) {
789 Arg
*CpuArg
= nullptr;
790 if (Arg
*A
= Args
.getLastArg(options::OPT_mcpu_EQ
))
793 StringRef CPU
= CpuArg
? CpuArg
->getValue() : GetDefaultCPU();
794 if (CPU
.startswith("hexagon"))
795 return CPU
.substr(sizeof("hexagon") - 1);