1 | |
2 | |
3 | |
4 | |
5 | |
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 | |
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 | .Case("v66", "128b") |
35 | .Default("128b"); |
36 | } |
37 | |
38 | static void handleHVXWarnings(const Driver &D, const ArgList &Args) { |
39 | |
40 | if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) { |
41 | StringRef Val = A->getValue(); |
42 | if (!Val.equals_lower("64b") && !Val.equals_lower("128b")) |
43 | D.Diag(diag::err_drv_unsupported_option_argument) |
44 | << A->getOption().getName() << Val; |
45 | } |
46 | } |
47 | |
48 | |
49 | static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args, |
50 | std::vector<StringRef> &Features, |
51 | bool &HasHVX) { |
52 | |
53 | handleHVXWarnings(D, Args); |
54 | |
55 | |
56 | StringRef HVXFeature, HVXLength; |
57 | StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args)); |
58 | |
59 | |
60 | if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx, |
61 | options::OPT_mhexagon_hvx, |
62 | options::OPT_mhexagon_hvx_EQ)) { |
63 | if (A->getOption().matches(options::OPT_mno_hexagon_hvx)) |
64 | return; |
65 | if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) { |
66 | HasHVX = true; |
67 | HVXFeature = Cpu = A->getValue(); |
68 | HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower()); |
69 | } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) { |
70 | HasHVX = true; |
71 | HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu); |
72 | } |
73 | Features.push_back(HVXFeature); |
74 | } |
75 | |
76 | |
77 | if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) { |
78 | |
79 | if (!HasHVX) |
80 | D.Diag(diag::err_drv_invalid_hvx_length); |
81 | else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ)) |
82 | HVXLength = A->getValue(); |
83 | } |
84 | |
85 | else if (HasHVX) |
86 | HVXLength = getDefaultHvxLength(Cpu); |
87 | |
88 | if (!HVXLength.empty()) { |
89 | HVXFeature = |
90 | Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower()); |
91 | Features.push_back(HVXFeature); |
92 | } |
93 | } |
94 | |
95 | |
96 | void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args, |
97 | std::vector<StringRef> &Features) { |
98 | handleTargetFeaturesGroup(Args, Features, |
99 | options::OPT_m_hexagon_Features_Group); |
100 | |
101 | bool UseLongCalls = false; |
102 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
103 | options::OPT_mno_long_calls)) { |
104 | if (A->getOption().matches(options::OPT_mlong_calls)) |
105 | UseLongCalls = true; |
106 | } |
107 | |
108 | Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls"); |
109 | |
110 | bool HasHVX = false; |
111 | handleHVXTargetFeatures(D, Args, Features, HasHVX); |
112 | |
113 | if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX) |
114 | D.Diag(diag::warn_drv_vectorize_needs_hvx); |
115 | } |
116 | |
117 | |
118 | void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA, |
119 | ArgStringList &CmdArgs) const { |
120 | } |
121 | |
122 | void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
123 | const InputInfo &Output, |
124 | const InputInfoList &Inputs, |
125 | const ArgList &Args, |
126 | const char *LinkingOutput) const { |
127 | claimNoWarnArgs(Args); |
128 | |
129 | auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); |
130 | const Driver &D = HTC.getDriver(); |
131 | ArgStringList CmdArgs; |
132 | |
133 | CmdArgs.push_back("-march=hexagon"); |
134 | |
135 | RenderExtraToolArgs(JA, CmdArgs); |
136 | |
137 | const char *AsName = "hexagon-llvm-mc"; |
138 | CmdArgs.push_back("-filetype=obj"); |
139 | CmdArgs.push_back(Args.MakeArgString( |
140 | "-mcpu=hexagon" + |
141 | toolchains::HexagonToolChain::GetTargetCPUVersion(Args))); |
142 | |
143 | if (Output.isFilename()) { |
144 | CmdArgs.push_back("-o"); |
145 | CmdArgs.push_back(Output.getFilename()); |
146 | } else { |
147 | (0) . __assert_fail ("Output.isNothing() && \"Unexpected output\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/Hexagon.cpp", 147, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Output.isNothing() && "Unexpected output"); |
148 | CmdArgs.push_back("-fsyntax-only"); |
149 | } |
150 | |
151 | if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { |
152 | CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue()))); |
153 | } |
154 | |
155 | Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | for (const auto &II : Inputs) { |
166 | |
167 | if (types::isLLVMIR(II.getType())) |
168 | D.Diag(clang::diag::err_drv_no_linker_llvm_support) |
169 | << HTC.getTripleString(); |
170 | else if (II.getType() == types::TY_AST) |
171 | D.Diag(clang::diag::err_drv_no_ast_support) |
172 | << HTC.getTripleString(); |
173 | else if (II.getType() == types::TY_ModuleFile) |
174 | D.Diag(diag::err_drv_no_module_support) |
175 | << HTC.getTripleString(); |
176 | |
177 | if (II.isFilename()) |
178 | CmdArgs.push_back(II.getFilename()); |
179 | else |
180 | |
181 | |
182 | II.getInputArg().render(Args, CmdArgs); |
183 | } |
184 | |
185 | auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); |
186 | C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); |
187 | } |
188 | |
189 | void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, |
190 | ArgStringList &CmdArgs) const { |
191 | } |
192 | |
193 | static void |
194 | constructHexagonLinkArgs(Compilation &C, const JobAction &JA, |
195 | const toolchains::HexagonToolChain &HTC, |
196 | const InputInfo &Output, const InputInfoList &Inputs, |
197 | const ArgList &Args, ArgStringList &CmdArgs, |
198 | const char *LinkingOutput) { |
199 | |
200 | const Driver &D = HTC.getDriver(); |
201 | |
202 | |
203 | |
204 | |
205 | bool IsStatic = Args.hasArg(options::OPT_static); |
206 | bool IsShared = Args.hasArg(options::OPT_shared); |
207 | bool IsPIE = Args.hasArg(options::OPT_pie); |
208 | bool IncStdLib = !Args.hasArg(options::OPT_nostdlib); |
209 | bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles); |
210 | bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); |
211 | bool UseG0 = false; |
212 | bool UseShared = IsShared && !IsStatic; |
213 | |
214 | |
215 | |
216 | |
217 | Args.ClaimAllArgs(options::OPT_g_Group); |
218 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
219 | Args.ClaimAllArgs(options::OPT_w); |
220 | |
221 | Args.ClaimAllArgs(options::OPT_static_libgcc); |
222 | |
223 | |
224 | |
225 | |
226 | if (Args.hasArg(options::OPT_s)) |
227 | CmdArgs.push_back("-s"); |
228 | |
229 | if (Args.hasArg(options::OPT_r)) |
230 | CmdArgs.push_back("-r"); |
231 | |
232 | for (const auto &Opt : HTC.ExtraOpts) |
233 | CmdArgs.push_back(Opt.c_str()); |
234 | |
235 | CmdArgs.push_back("-march=hexagon"); |
236 | StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args); |
237 | CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer)); |
238 | |
239 | if (IsShared) { |
240 | CmdArgs.push_back("-shared"); |
241 | |
242 | CmdArgs.push_back("-call_shared"); |
243 | } |
244 | |
245 | if (IsStatic) |
246 | CmdArgs.push_back("-static"); |
247 | |
248 | if (IsPIE && !IsShared) |
249 | CmdArgs.push_back("-pie"); |
250 | |
251 | if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { |
252 | CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue()))); |
253 | UseG0 = G.getValue() == 0; |
254 | } |
255 | |
256 | |
257 | |
258 | |
259 | CmdArgs.push_back("-o"); |
260 | CmdArgs.push_back(Output.getFilename()); |
261 | |
262 | |
263 | |
264 | |
265 | std::vector<std::string> OsLibs; |
266 | bool HasStandalone = false; |
267 | |
268 | for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) { |
269 | A->claim(); |
270 | OsLibs.emplace_back(A->getValue()); |
271 | HasStandalone = HasStandalone || (OsLibs.back() == "standalone"); |
272 | } |
273 | if (OsLibs.empty()) { |
274 | OsLibs.push_back("standalone"); |
275 | HasStandalone = true; |
276 | } |
277 | |
278 | |
279 | |
280 | |
281 | const std::string MCpuSuffix = "/" + CpuVer.str(); |
282 | const std::string MCpuG0Suffix = MCpuSuffix + "/G0"; |
283 | const std::string RootDir = |
284 | HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/"; |
285 | const std::string StartSubDir = |
286 | "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix); |
287 | |
288 | auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir, |
289 | const char *Name) -> std::string { |
290 | std::string RelName = SubDir + Name; |
291 | std::string P = HTC.GetFilePath(RelName.c_str()); |
292 | if (llvm::sys::fs::exists(P)) |
293 | return P; |
294 | return RootDir + RelName; |
295 | }; |
296 | |
297 | if (IncStdLib && IncStartFiles) { |
298 | if (!IsShared) { |
299 | if (HasStandalone) { |
300 | std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o"); |
301 | CmdArgs.push_back(Args.MakeArgString(Crt0SA)); |
302 | } |
303 | std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o"); |
304 | CmdArgs.push_back(Args.MakeArgString(Crt0)); |
305 | } |
306 | std::string Init = UseShared |
307 | ? Find(RootDir, StartSubDir + "/pic", "/initS.o") |
308 | : Find(RootDir, StartSubDir, "/init.o"); |
309 | CmdArgs.push_back(Args.MakeArgString(Init)); |
310 | } |
311 | |
312 | |
313 | |
314 | |
315 | const ToolChain::path_list &LibPaths = HTC.getFilePaths(); |
316 | for (const auto &LibPath : LibPaths) |
317 | CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); |
318 | |
319 | |
320 | |
321 | |
322 | Args.AddAllArgs(CmdArgs, |
323 | {options::OPT_T_Group, options::OPT_e, options::OPT_s, |
324 | options::OPT_t, options::OPT_u_Group}); |
325 | |
326 | AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); |
327 | |
328 | |
329 | |
330 | |
331 | if (IncStdLib && IncDefLibs) { |
332 | if (D.CCCIsCXX()) { |
333 | if (HTC.ShouldLinkCXXStdlib(Args)) |
334 | HTC.AddCXXStdlibLibArgs(Args, CmdArgs); |
335 | CmdArgs.push_back("-lm"); |
336 | } |
337 | |
338 | CmdArgs.push_back("--start-group"); |
339 | |
340 | if (!IsShared) { |
341 | for (StringRef Lib : OsLibs) |
342 | CmdArgs.push_back(Args.MakeArgString("-l" + Lib)); |
343 | CmdArgs.push_back("-lc"); |
344 | } |
345 | CmdArgs.push_back("-lgcc"); |
346 | |
347 | CmdArgs.push_back("--end-group"); |
348 | } |
349 | |
350 | |
351 | |
352 | |
353 | if (IncStdLib && IncStartFiles) { |
354 | std::string Fini = UseShared |
355 | ? Find(RootDir, StartSubDir + "/pic", "/finiS.o") |
356 | : Find(RootDir, StartSubDir, "/fini.o"); |
357 | CmdArgs.push_back(Args.MakeArgString(Fini)); |
358 | } |
359 | } |
360 | |
361 | void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
362 | const InputInfo &Output, |
363 | const InputInfoList &Inputs, |
364 | const ArgList &Args, |
365 | const char *LinkingOutput) const { |
366 | auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); |
367 | |
368 | ArgStringList CmdArgs; |
369 | constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs, |
370 | LinkingOutput); |
371 | |
372 | const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); |
373 | C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); |
374 | } |
375 | |
376 | |
377 | |
378 | |
379 | std::string HexagonToolChain::getHexagonTargetDir( |
380 | const std::string &InstalledDir, |
381 | const SmallVectorImpl<std::string> &PrefixDirs) const { |
382 | std::string InstallRelDir; |
383 | const Driver &D = getDriver(); |
384 | |
385 | |
386 | for (auto &I : PrefixDirs) |
387 | if (D.getVFS().exists(I)) |
388 | return I; |
389 | |
390 | if (getVFS().exists(InstallRelDir = InstalledDir + "/../target")) |
391 | return InstallRelDir; |
392 | |
393 | return InstalledDir; |
394 | } |
395 | |
396 | Optional<unsigned> HexagonToolChain::getSmallDataThreshold( |
397 | const ArgList &Args) { |
398 | StringRef Gn = ""; |
399 | if (Arg *A = Args.getLastArg(options::OPT_G)) { |
400 | Gn = A->getValue(); |
401 | } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, |
402 | options::OPT_fPIC)) { |
403 | Gn = "0"; |
404 | } |
405 | |
406 | unsigned G; |
407 | if (!Gn.getAsInteger(10, G)) |
408 | return G; |
409 | |
410 | return None; |
411 | } |
412 | |
413 | void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, |
414 | ToolChain::path_list &LibPaths) const { |
415 | const Driver &D = getDriver(); |
416 | |
417 | |
418 | |
419 | |
420 | for (Arg *A : Args.filtered(options::OPT_L)) |
421 | for (const char *Value : A->getValues()) |
422 | LibPaths.push_back(Value); |
423 | |
424 | |
425 | |
426 | |
427 | std::vector<std::string> RootDirs; |
428 | std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), |
429 | std::back_inserter(RootDirs)); |
430 | |
431 | std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
432 | D.PrefixDirs); |
433 | if (std::find(RootDirs.begin(), RootDirs.end(), TargetDir) == RootDirs.end()) |
434 | RootDirs.push_back(TargetDir); |
435 | |
436 | bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC); |
437 | |
438 | bool HasG0 = Args.hasArg(options::OPT_shared); |
439 | if (auto G = getSmallDataThreshold(Args)) |
440 | HasG0 = G.getValue() == 0; |
441 | |
442 | const std::string CpuVer = GetTargetCPUVersion(Args).str(); |
443 | for (auto &Dir : RootDirs) { |
444 | std::string LibDir = Dir + "/hexagon/lib"; |
445 | std::string LibDirCpu = LibDir + '/' + CpuVer; |
446 | if (HasG0) { |
447 | if (HasPIC) |
448 | LibPaths.push_back(LibDirCpu + "/G0/pic"); |
449 | LibPaths.push_back(LibDirCpu + "/G0"); |
450 | } |
451 | LibPaths.push_back(LibDirCpu); |
452 | LibPaths.push_back(LibDir); |
453 | } |
454 | } |
455 | |
456 | HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple, |
457 | const llvm::opt::ArgList &Args) |
458 | : Linux(D, Triple, Args) { |
459 | const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
460 | D.PrefixDirs); |
461 | |
462 | |
463 | |
464 | const std::string BinDir(TargetDir + "/bin"); |
465 | if (D.getVFS().exists(BinDir)) |
466 | getProgramPaths().push_back(BinDir); |
467 | |
468 | ToolChain::path_list &LibPaths = getFilePaths(); |
469 | |
470 | |
471 | |
472 | |
473 | LibPaths.clear(); |
474 | getHexagonLibraryPaths(Args, LibPaths); |
475 | } |
476 | |
477 | HexagonToolChain::~HexagonToolChain() {} |
478 | |
479 | Tool *HexagonToolChain::buildAssembler() const { |
480 | return new tools::hexagon::Assembler(*this); |
481 | } |
482 | |
483 | Tool *HexagonToolChain::buildLinker() const { |
484 | return new tools::hexagon::Linker(*this); |
485 | } |
486 | |
487 | unsigned HexagonToolChain::getOptimizationLevel( |
488 | const llvm::opt::ArgList &DriverArgs) const { |
489 | |
490 | Arg *A = DriverArgs.getLastArg(options::OPT_O_Group); |
491 | if (!A) |
492 | return 0; |
493 | |
494 | if (A->getOption().matches(options::OPT_O0)) |
495 | return 0; |
496 | if (A->getOption().matches(options::OPT_Ofast) || |
497 | A->getOption().matches(options::OPT_O4)) |
498 | return 3; |
499 | getNumValues() != 0", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/Hexagon.cpp", 499, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(A->getNumValues() != 0); |
500 | StringRef S(A->getValue()); |
501 | if (S == "s" || S == "z" || S.empty()) |
502 | return 2; |
503 | if (S == "g") |
504 | return 1; |
505 | |
506 | unsigned OptLevel; |
507 | if (S.getAsInteger(10, OptLevel)) |
508 | return 0; |
509 | return OptLevel; |
510 | } |
511 | |
512 | void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs, |
513 | ArgStringList &CC1Args, |
514 | Action::OffloadKind) const { |
515 | if (DriverArgs.hasArg(options::OPT_ffixed_r19)) { |
516 | CC1Args.push_back("-target-feature"); |
517 | CC1Args.push_back("+reserved-r19"); |
518 | } |
519 | if (isAutoHVXEnabled(DriverArgs)) { |
520 | CC1Args.push_back("-mllvm"); |
521 | CC1Args.push_back("-hexagon-autohvx"); |
522 | } |
523 | } |
524 | |
525 | void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
526 | ArgStringList &CC1Args) const { |
527 | if (DriverArgs.hasArg(options::OPT_nostdinc) || |
528 | DriverArgs.hasArg(options::OPT_nostdlibinc)) |
529 | return; |
530 | |
531 | const Driver &D = getDriver(); |
532 | std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), |
533 | D.PrefixDirs); |
534 | addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include"); |
535 | } |
536 | |
537 | |
538 | void HexagonToolChain::addLibStdCxxIncludePaths( |
539 | const llvm::opt::ArgList &DriverArgs, |
540 | llvm::opt::ArgStringList &CC1Args) const { |
541 | const Driver &D = getDriver(); |
542 | std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); |
543 | addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "", |
544 | DriverArgs, CC1Args); |
545 | } |
546 | |
547 | ToolChain::CXXStdlibType |
548 | HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const { |
549 | Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); |
550 | if (!A) |
551 | return ToolChain::CST_Libstdcxx; |
552 | |
553 | StringRef Value = A->getValue(); |
554 | if (Value != "libstdc++") |
555 | getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); |
556 | |
557 | return ToolChain::CST_Libstdcxx; |
558 | } |
559 | |
560 | bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) { |
561 | if (Arg *A = Args.getLastArg(options::OPT_fvectorize, |
562 | options::OPT_fno_vectorize)) |
563 | return A->getOption().matches(options::OPT_fvectorize); |
564 | return false; |
565 | } |
566 | |
567 | |
568 | |
569 | |
570 | |
571 | const StringRef HexagonToolChain::GetDefaultCPU() { |
572 | return "hexagonv60"; |
573 | } |
574 | |
575 | const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) { |
576 | Arg *CpuArg = nullptr; |
577 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ)) |
578 | CpuArg = A; |
579 | |
580 | StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU(); |
581 | if (CPU.startswith("hexagon")) |
582 | return CPU.substr(sizeof("hexagon") - 1); |
583 | return CPU; |
584 | } |
585 | |