blob: ea100fbccedd371b9b72621a1cb6a9c291594571 [file] [log] [blame]
David L. Jonesf561aba2017-03-08 01:02:16 +00001//===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Hexagon.h"
11#include "InputInfo.h"
12#include "CommonArgs.h"
13#include "clang/Basic/VirtualFileSystem.h"
14#include "clang/Config/config.h"
15#include "clang/Driver/Compilation.h"
16#include "clang/Driver/Driver.h"
17#include "clang/Driver/DriverDiagnostic.h"
18#include "clang/Driver/Options.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Support/FileSystem.h"
22#include "llvm/Support/Path.h"
23
24using namespace clang::driver;
25using namespace clang::driver::tools;
26using namespace clang::driver::toolchains;
27using namespace clang;
28using namespace llvm::opt;
29
Sumanth Gundapaneni57098f52017-10-18 18:10:13 +000030// Default hvx-length for various versions.
31static std::string getDefaultHvxLength(const StringRef &Cpu) {
32 return llvm::StringSwitch<std::string>(Cpu)
33 .Case("v60", "64b")
34 .Case("v62", "64b")
35 .Default("128b");
36}
37
38static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
39 // Handle deprecated HVX double warnings.
40 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_double))
41 D.Diag(diag::warn_drv_deprecated_arg)
42 << A->getAsString(Args) << "-mhvx-length=128B";
43 if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx_double))
44 D.Diag(diag::warn_drv_deprecated_arg) << A->getAsString(Args) << "-mno-hvx";
45 // Handle the unsupported values passed to mhvx-length.
46 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
47 StringRef Val = A->getValue();
48 if (Val != "64B" && Val != "128B")
49 D.Diag(diag::err_drv_unsupported_option_argument)
50 << A->getOption().getName() << Val;
51 }
52}
53
54// Handle hvx target features explicitly.
55static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
56 std::vector<StringRef> &Features,
57 bool &HasHVX) {
58 // Handle HVX warnings.
59 handleHVXWarnings(D, Args);
60
61 // Add the +hvx* features based on commandline flags.
62 StringRef HVXFeature, HVXLength;
63 StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
64
65 // Handle -mhvx, -mhvx=, -mno-hvx, -mno-hvx-double.
66 if (Arg *A = Args.getLastArg(
67 options::OPT_mno_hexagon_hvx, options::OPT_mno_hexagon_hvx_double,
68 options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ)) {
69 if (A->getOption().matches(options::OPT_mno_hexagon_hvx) ||
70 A->getOption().matches(options::OPT_mno_hexagon_hvx_double)) {
71 return;
72 } else if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
73 HasHVX = true;
74 HVXFeature = Cpu = A->getValue();
75 HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
76 } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) {
77 HasHVX = true;
78 HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu);
79 }
80 Features.push_back(HVXFeature);
81 }
82
83 // Handle -mhvx-length=, -mhvx-double.
84 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ,
85 options::OPT_mhexagon_hvx_double)) {
86 // These falgs are valid only if HVX in enabled.
87 if (!HasHVX)
88 D.Diag(diag::err_drv_invalid_hvx_length);
89 else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
90 HVXLength = A->getValue();
91 else if (A->getOption().matches(options::OPT_mhexagon_hvx_double))
92 HVXLength = "128b";
93 }
94 // Default hvx-length based on Cpu.
95 else if (HasHVX)
96 HVXLength = StringRef(getDefaultHvxLength(Cpu));
97
98 if (!HVXLength.empty()) {
99 HVXFeature =
100 Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower());
101 Features.push_back(HVXFeature);
102 }
103}
104
Sumanth Gundapaneni2d9aa742017-10-04 19:09:29 +0000105// Hexagon target features.
Sumanth Gundapaneni57098f52017-10-18 18:10:13 +0000106void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
Sumanth Gundapaneni2d9aa742017-10-04 19:09:29 +0000107 std::vector<StringRef> &Features) {
108 handleTargetFeaturesGroup(Args, Features,
109 options::OPT_m_hexagon_Features_Group);
110
111 bool UseLongCalls = false;
112 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
113 options::OPT_mno_long_calls)) {
114 if (A->getOption().matches(options::OPT_mlong_calls))
115 UseLongCalls = true;
116 }
117
118 Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
Sumanth Gundapaneni57098f52017-10-18 18:10:13 +0000119
120 bool HasHVX(false);
121 handleHVXTargetFeatures(D, Args, Features, HasHVX);
Sumanth Gundapaneni2d9aa742017-10-04 19:09:29 +0000122}
123
David L. Jonesf561aba2017-03-08 01:02:16 +0000124// Hexagon tools start.
125void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
126 ArgStringList &CmdArgs) const {
127}
128
129void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
130 const InputInfo &Output,
131 const InputInfoList &Inputs,
132 const ArgList &Args,
133 const char *LinkingOutput) const {
134 claimNoWarnArgs(Args);
135
136 auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
137 const Driver &D = HTC.getDriver();
138 ArgStringList CmdArgs;
139
140 std::string MArchString = "-march=hexagon";
141 CmdArgs.push_back(Args.MakeArgString(MArchString));
142
143 RenderExtraToolArgs(JA, CmdArgs);
144
145 std::string AsName = "hexagon-llvm-mc";
146 std::string MCpuString = "-mcpu=hexagon" +
147 toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
148 CmdArgs.push_back("-filetype=obj");
149 CmdArgs.push_back(Args.MakeArgString(MCpuString));
150
151 if (Output.isFilename()) {
152 CmdArgs.push_back("-o");
153 CmdArgs.push_back(Output.getFilename());
154 } else {
155 assert(Output.isNothing() && "Unexpected output");
156 CmdArgs.push_back("-fsyntax-only");
157 }
158
159 if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
160 std::string N = llvm::utostr(G.getValue());
161 CmdArgs.push_back(Args.MakeArgString(std::string("-gpsize=") + N));
162 }
163
164 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
165
166 // Only pass -x if gcc will understand it; otherwise hope gcc
167 // understands the suffix correctly. The main use case this would go
168 // wrong in is for linker inputs if they happened to have an odd
169 // suffix; really the only way to get this to happen is a command
170 // like '-x foobar a.c' which will treat a.c like a linker input.
171 //
172 // FIXME: For the linker case specifically, can we safely convert
173 // inputs into '-Wl,' options?
174 for (const auto &II : Inputs) {
175 // Don't try to pass LLVM or AST inputs to a generic gcc.
176 if (types::isLLVMIR(II.getType()))
177 D.Diag(clang::diag::err_drv_no_linker_llvm_support)
178 << HTC.getTripleString();
179 else if (II.getType() == types::TY_AST)
180 D.Diag(clang::diag::err_drv_no_ast_support)
181 << HTC.getTripleString();
182 else if (II.getType() == types::TY_ModuleFile)
183 D.Diag(diag::err_drv_no_module_support)
184 << HTC.getTripleString();
185
186 if (II.isFilename())
187 CmdArgs.push_back(II.getFilename());
188 else
189 // Don't render as input, we need gcc to do the translations.
190 // FIXME: What is this?
191 II.getInputArg().render(Args, CmdArgs);
192 }
193
194 auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str()));
195 C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
196}
197
198void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
199 ArgStringList &CmdArgs) const {
200}
201
202static void
203constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
204 const toolchains::HexagonToolChain &HTC,
205 const InputInfo &Output, const InputInfoList &Inputs,
206 const ArgList &Args, ArgStringList &CmdArgs,
207 const char *LinkingOutput) {
208
209 const Driver &D = HTC.getDriver();
210
211 //----------------------------------------------------------------------------
212 //
213 //----------------------------------------------------------------------------
214 bool IsStatic = Args.hasArg(options::OPT_static);
215 bool IsShared = Args.hasArg(options::OPT_shared);
216 bool IsPIE = Args.hasArg(options::OPT_pie);
217 bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
218 bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
219 bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
220 bool UseG0 = false;
221 bool UseShared = IsShared && !IsStatic;
222
223 //----------------------------------------------------------------------------
224 // Silence warnings for various options
225 //----------------------------------------------------------------------------
226 Args.ClaimAllArgs(options::OPT_g_Group);
227 Args.ClaimAllArgs(options::OPT_emit_llvm);
228 Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
229 // handled somewhere else.
230 Args.ClaimAllArgs(options::OPT_static_libgcc);
231
232 //----------------------------------------------------------------------------
233 //
234 //----------------------------------------------------------------------------
235 if (Args.hasArg(options::OPT_s))
236 CmdArgs.push_back("-s");
237
238 if (Args.hasArg(options::OPT_r))
239 CmdArgs.push_back("-r");
240
241 for (const auto &Opt : HTC.ExtraOpts)
242 CmdArgs.push_back(Opt.c_str());
243
244 CmdArgs.push_back("-march=hexagon");
245 std::string CpuVer =
246 toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
247 std::string MCpuString = "-mcpu=hexagon" + CpuVer;
248 CmdArgs.push_back(Args.MakeArgString(MCpuString));
249
250 if (IsShared) {
251 CmdArgs.push_back("-shared");
252 // The following should be the default, but doing as hexagon-gcc does.
253 CmdArgs.push_back("-call_shared");
254 }
255
256 if (IsStatic)
257 CmdArgs.push_back("-static");
258
259 if (IsPIE && !IsShared)
260 CmdArgs.push_back("-pie");
261
262 if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
263 std::string N = llvm::utostr(G.getValue());
264 CmdArgs.push_back(Args.MakeArgString(std::string("-G") + N));
265 UseG0 = G.getValue() == 0;
266 }
267
268 //----------------------------------------------------------------------------
269 //
270 //----------------------------------------------------------------------------
271 CmdArgs.push_back("-o");
272 CmdArgs.push_back(Output.getFilename());
273
274 //----------------------------------------------------------------------------
275 // moslib
276 //----------------------------------------------------------------------------
277 std::vector<std::string> OsLibs;
278 bool HasStandalone = false;
279
280 for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
281 A->claim();
282 OsLibs.emplace_back(A->getValue());
283 HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
284 }
285 if (OsLibs.empty()) {
286 OsLibs.push_back("standalone");
287 HasStandalone = true;
288 }
289
290 //----------------------------------------------------------------------------
291 // Start Files
292 //----------------------------------------------------------------------------
293 const std::string MCpuSuffix = "/" + CpuVer;
294 const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
295 const std::string RootDir =
296 HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
297 const std::string StartSubDir =
298 "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
299
300 auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
301 const char *Name) -> std::string {
302 std::string RelName = SubDir + Name;
303 std::string P = HTC.GetFilePath(RelName.c_str());
304 if (llvm::sys::fs::exists(P))
305 return P;
306 return RootDir + RelName;
307 };
308
309 if (IncStdLib && IncStartFiles) {
310 if (!IsShared) {
311 if (HasStandalone) {
312 std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
313 CmdArgs.push_back(Args.MakeArgString(Crt0SA));
314 }
315 std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
316 CmdArgs.push_back(Args.MakeArgString(Crt0));
317 }
318 std::string Init = UseShared
319 ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
320 : Find(RootDir, StartSubDir, "/init.o");
321 CmdArgs.push_back(Args.MakeArgString(Init));
322 }
323
324 //----------------------------------------------------------------------------
325 // Library Search Paths
326 //----------------------------------------------------------------------------
327 const ToolChain::path_list &LibPaths = HTC.getFilePaths();
328 for (const auto &LibPath : LibPaths)
329 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
330
331 //----------------------------------------------------------------------------
332 //
333 //----------------------------------------------------------------------------
334 Args.AddAllArgs(CmdArgs,
335 {options::OPT_T_Group, options::OPT_e, options::OPT_s,
336 options::OPT_t, options::OPT_u_Group});
337
338 AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
339
340 //----------------------------------------------------------------------------
341 // Libraries
342 //----------------------------------------------------------------------------
343 if (IncStdLib && IncDefLibs) {
344 if (D.CCCIsCXX()) {
Nico Weber0ee47d92017-07-25 18:02:57 +0000345 if (HTC.ShouldLinkCXXStdlib(Args))
346 HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
David L. Jonesf561aba2017-03-08 01:02:16 +0000347 CmdArgs.push_back("-lm");
348 }
349
350 CmdArgs.push_back("--start-group");
351
352 if (!IsShared) {
353 for (const std::string &Lib : OsLibs)
354 CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
355 CmdArgs.push_back("-lc");
356 }
357 CmdArgs.push_back("-lgcc");
358
359 CmdArgs.push_back("--end-group");
360 }
361
362 //----------------------------------------------------------------------------
363 // End files
364 //----------------------------------------------------------------------------
365 if (IncStdLib && IncStartFiles) {
366 std::string Fini = UseShared
367 ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
368 : Find(RootDir, StartSubDir, "/fini.o");
369 CmdArgs.push_back(Args.MakeArgString(Fini));
370 }
371}
372
373void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
374 const InputInfo &Output,
375 const InputInfoList &Inputs,
376 const ArgList &Args,
377 const char *LinkingOutput) const {
378 auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
379
380 ArgStringList CmdArgs;
381 constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
382 LinkingOutput);
383
384 std::string Linker = HTC.GetProgramPath("hexagon-link");
385 C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
386 CmdArgs, Inputs));
387}
388// Hexagon tools end.
389
390/// Hexagon Toolchain
391
392std::string HexagonToolChain::getHexagonTargetDir(
393 const std::string &InstalledDir,
394 const SmallVectorImpl<std::string> &PrefixDirs) const {
395 std::string InstallRelDir;
396 const Driver &D = getDriver();
397
398 // Locate the rest of the toolchain ...
399 for (auto &I : PrefixDirs)
400 if (D.getVFS().exists(I))
401 return I;
402
403 if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
404 return InstallRelDir;
405
406 return InstalledDir;
407}
408
409Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
410 const ArgList &Args) {
411 StringRef Gn = "";
412 if (Arg *A = Args.getLastArg(options::OPT_G)) {
413 Gn = A->getValue();
414 } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
415 options::OPT_fPIC)) {
416 Gn = "0";
417 }
418
419 unsigned G;
420 if (!Gn.getAsInteger(10, G))
421 return G;
422
423 return None;
424}
425
426void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
427 ToolChain::path_list &LibPaths) const {
428 const Driver &D = getDriver();
429
430 //----------------------------------------------------------------------------
431 // -L Args
432 //----------------------------------------------------------------------------
433 for (Arg *A : Args.filtered(options::OPT_L))
434 for (const char *Value : A->getValues())
435 LibPaths.push_back(Value);
436
437 //----------------------------------------------------------------------------
438 // Other standard paths
439 //----------------------------------------------------------------------------
440 std::vector<std::string> RootDirs;
441 std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
442 std::back_inserter(RootDirs));
443
444 std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
445 D.PrefixDirs);
446 if (std::find(RootDirs.begin(), RootDirs.end(), TargetDir) == RootDirs.end())
447 RootDirs.push_back(TargetDir);
448
449 bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
450 // Assume G0 with -shared.
451 bool HasG0 = Args.hasArg(options::OPT_shared);
452 if (auto G = getSmallDataThreshold(Args))
453 HasG0 = G.getValue() == 0;
454
455 const std::string CpuVer = GetTargetCPUVersion(Args).str();
456 for (auto &Dir : RootDirs) {
457 std::string LibDir = Dir + "/hexagon/lib";
458 std::string LibDirCpu = LibDir + '/' + CpuVer;
459 if (HasG0) {
460 if (HasPIC)
461 LibPaths.push_back(LibDirCpu + "/G0/pic");
462 LibPaths.push_back(LibDirCpu + "/G0");
463 }
464 LibPaths.push_back(LibDirCpu);
465 LibPaths.push_back(LibDir);
466 }
467}
468
469HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
470 const llvm::opt::ArgList &Args)
471 : Linux(D, Triple, Args) {
472 const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
473 D.PrefixDirs);
474
475 // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
476 // program paths
477 const std::string BinDir(TargetDir + "/bin");
478 if (D.getVFS().exists(BinDir))
479 getProgramPaths().push_back(BinDir);
480
481 ToolChain::path_list &LibPaths = getFilePaths();
482
483 // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
484 // 'elf' OS type, so the Linux paths are not appropriate. When we actually
485 // support 'linux' we'll need to fix this up
486 LibPaths.clear();
487 getHexagonLibraryPaths(Args, LibPaths);
488}
489
490HexagonToolChain::~HexagonToolChain() {}
491
492Tool *HexagonToolChain::buildAssembler() const {
493 return new tools::hexagon::Assembler(*this);
494}
495
496Tool *HexagonToolChain::buildLinker() const {
497 return new tools::hexagon::Linker(*this);
498}
499
Krzysztof Parzyszekdcda9452017-04-25 20:51:51 +0000500unsigned HexagonToolChain::getOptimizationLevel(
501 const llvm::opt::ArgList &DriverArgs) const {
502 // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
503 Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
504 if (!A)
505 return 0;
506
507 if (A->getOption().matches(options::OPT_O0))
508 return 0;
Krzysztof Parzyszekd6d41272017-04-25 21:31:55 +0000509 if (A->getOption().matches(options::OPT_Ofast) ||
510 A->getOption().matches(options::OPT_O4))
Krzysztof Parzyszekdcda9452017-04-25 20:51:51 +0000511 return 3;
512 assert(A->getNumValues() != 0);
513 StringRef S(A->getValue());
514 if (S == "s" || S == "z" || S.empty())
515 return 2;
516 if (S == "g")
517 return 1;
518
519 unsigned OptLevel;
520 if (S.getAsInteger(10, OptLevel))
521 return 0;
522 return OptLevel;
523}
524
525void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
Gheorghe-Teodor Berceaf0f29602017-07-06 16:22:21 +0000526 ArgStringList &CC1Args,
527 Action::OffloadKind) const {
Krzysztof Parzyszekdcda9452017-04-25 20:51:51 +0000528 if (DriverArgs.hasArg(options::OPT_ffp_contract))
529 return;
530 unsigned OptLevel = getOptimizationLevel(DriverArgs);
531 if (OptLevel >= 3)
532 CC1Args.push_back("-ffp-contract=fast");
533}
534
David L. Jonesf561aba2017-03-08 01:02:16 +0000535void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
536 ArgStringList &CC1Args) const {
537 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
538 DriverArgs.hasArg(options::OPT_nostdlibinc))
539 return;
540
541 const Driver &D = getDriver();
542 std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
543 D.PrefixDirs);
544 addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
545}
546
547
548void HexagonToolChain::addLibStdCxxIncludePaths(
549 const llvm::opt::ArgList &DriverArgs,
550 llvm::opt::ArgStringList &CC1Args) const {
551 const Driver &D = getDriver();
552 std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
553 addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
554 DriverArgs, CC1Args);
555}
556
557ToolChain::CXXStdlibType
558HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
559 Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
560 if (!A)
561 return ToolChain::CST_Libstdcxx;
562
563 StringRef Value = A->getValue();
564 if (Value != "libstdc++")
565 getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
566
567 return ToolChain::CST_Libstdcxx;
568}
569
570//
571// Returns the default CPU for Hexagon. This is the default compilation target
572// if no Hexagon processor is selected at the command-line.
573//
574const StringRef HexagonToolChain::GetDefaultCPU() {
575 return "hexagonv60";
576}
577
578const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
579 Arg *CpuArg = nullptr;
580 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
581 CpuArg = A;
582
583 StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
584 if (CPU.startswith("hexagon"))
585 return CPU.substr(sizeof("hexagon") - 1);
586 return CPU;
587}