1 //===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Hexagon.h" 10 #include "CommonArgs.h" 11 #include "InputInfo.h" 12 #include "clang/Driver/Compilation.h" 13 #include "clang/Driver/Driver.h" 14 #include "clang/Driver/DriverDiagnostic.h" 15 #include "clang/Driver/Options.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/Option/ArgList.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 20 #include "llvm/Support/VirtualFileSystem.h" 21 22 using namespace clang::driver; 23 using namespace clang::driver::tools; 24 using namespace clang::driver::toolchains; 25 using namespace clang; 26 using namespace llvm::opt; 27 28 // Default hvx-length for various versions. 29 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 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. 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. 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. 124 void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA, 125 ArgStringList &CmdArgs) const { 126 } 127 128 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>( 193 JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); 194 } 195 196 void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, 197 ArgStringList &CmdArgs) const { 198 } 199 200 static void 201 constructHexagonLinkArgs(Compilation &C, const JobAction &JA, 202 const toolchains::HexagonToolChain &HTC, 203 const InputInfo &Output, const InputInfoList &Inputs, 204 const ArgList &Args, ArgStringList &CmdArgs, 205 const char *LinkingOutput) { 206 207 const Driver &D = HTC.getDriver(); 208 209 //---------------------------------------------------------------------------- 210 // 211 //---------------------------------------------------------------------------- 212 bool IsStatic = Args.hasArg(options::OPT_static); 213 bool IsShared = Args.hasArg(options::OPT_shared); 214 bool IsPIE = Args.hasArg(options::OPT_pie); 215 bool IncStdLib = !Args.hasArg(options::OPT_nostdlib); 216 bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles); 217 bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); 218 bool UseG0 = false; 219 const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); 220 bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") || 221 llvm::sys::path::stem(Exec).equals_lower("ld.lld")); 222 bool UseShared = IsShared && !IsStatic; 223 StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args); 224 225 //---------------------------------------------------------------------------- 226 // Silence warnings for various options 227 //---------------------------------------------------------------------------- 228 Args.ClaimAllArgs(options::OPT_g_Group); 229 Args.ClaimAllArgs(options::OPT_emit_llvm); 230 Args.ClaimAllArgs(options::OPT_w); // Other warning options are already 231 // handled somewhere else. 232 Args.ClaimAllArgs(options::OPT_static_libgcc); 233 234 //---------------------------------------------------------------------------- 235 // 236 //---------------------------------------------------------------------------- 237 if (Args.hasArg(options::OPT_s)) 238 CmdArgs.push_back("-s"); 239 240 if (Args.hasArg(options::OPT_r)) 241 CmdArgs.push_back("-r"); 242 243 for (const auto &Opt : HTC.ExtraOpts) 244 CmdArgs.push_back(Opt.c_str()); 245 246 if (!UseLLD) { 247 CmdArgs.push_back("-march=hexagon"); 248 CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer)); 249 } 250 251 if (IsShared) { 252 CmdArgs.push_back("-shared"); 253 // The following should be the default, but doing as hexagon-gcc does. 254 CmdArgs.push_back("-call_shared"); 255 } 256 257 if (IsStatic) 258 CmdArgs.push_back("-static"); 259 260 if (IsPIE && !IsShared) 261 CmdArgs.push_back("-pie"); 262 263 if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { 264 CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue()))); 265 UseG0 = G.getValue() == 0; 266 } 267 268 CmdArgs.push_back("-o"); 269 CmdArgs.push_back(Output.getFilename()); 270 271 if (HTC.getTriple().isMusl()) { 272 if (!Args.hasArg(options::OPT_shared, options::OPT_static)) 273 CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1"); 274 275 if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles, 276 options::OPT_nostdlib)) 277 CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o")); 278 else if (Args.hasArg(options::OPT_shared) && 279 !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib)) 280 CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o")); 281 282 CmdArgs.push_back( 283 Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib")); 284 Args.AddAllArgs(CmdArgs, 285 {options::OPT_T_Group, options::OPT_e, options::OPT_s, 286 options::OPT_t, options::OPT_u_Group}); 287 AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); 288 289 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 290 CmdArgs.push_back("-lclang_rt.builtins-hexagon"); 291 CmdArgs.push_back("-lc"); 292 } 293 if (D.CCCIsCXX()) { 294 if (HTC.ShouldLinkCXXStdlib(Args)) 295 HTC.AddCXXStdlibLibArgs(Args, CmdArgs); 296 } 297 return; 298 } 299 300 //---------------------------------------------------------------------------- 301 // moslib 302 //---------------------------------------------------------------------------- 303 std::vector<std::string> OsLibs; 304 bool HasStandalone = false; 305 for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) { 306 A->claim(); 307 OsLibs.emplace_back(A->getValue()); 308 HasStandalone = HasStandalone || (OsLibs.back() == "standalone"); 309 } 310 if (OsLibs.empty()) { 311 OsLibs.push_back("standalone"); 312 HasStandalone = true; 313 } 314 315 //---------------------------------------------------------------------------- 316 // Start Files 317 //---------------------------------------------------------------------------- 318 const std::string MCpuSuffix = "/" + CpuVer.str(); 319 const std::string MCpuG0Suffix = MCpuSuffix + "/G0"; 320 const std::string RootDir = 321 HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/"; 322 const std::string StartSubDir = 323 "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix); 324 325 auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir, 326 const char *Name) -> std::string { 327 std::string RelName = SubDir + Name; 328 std::string P = HTC.GetFilePath(RelName.c_str()); 329 if (llvm::sys::fs::exists(P)) 330 return P; 331 return RootDir + RelName; 332 }; 333 334 if (IncStdLib && IncStartFiles) { 335 if (!IsShared) { 336 if (HasStandalone) { 337 std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o"); 338 CmdArgs.push_back(Args.MakeArgString(Crt0SA)); 339 } 340 std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o"); 341 CmdArgs.push_back(Args.MakeArgString(Crt0)); 342 } 343 std::string Init = UseShared 344 ? Find(RootDir, StartSubDir + "/pic", "/initS.o") 345 : Find(RootDir, StartSubDir, "/init.o"); 346 CmdArgs.push_back(Args.MakeArgString(Init)); 347 } 348 349 //---------------------------------------------------------------------------- 350 // Library Search Paths 351 //---------------------------------------------------------------------------- 352 const ToolChain::path_list &LibPaths = HTC.getFilePaths(); 353 for (const auto &LibPath : LibPaths) 354 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); 355 356 //---------------------------------------------------------------------------- 357 // 358 //---------------------------------------------------------------------------- 359 Args.AddAllArgs(CmdArgs, 360 {options::OPT_T_Group, options::OPT_e, options::OPT_s, 361 options::OPT_t, options::OPT_u_Group}); 362 363 AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); 364 365 //---------------------------------------------------------------------------- 366 // Libraries 367 //---------------------------------------------------------------------------- 368 if (IncStdLib && IncDefLibs) { 369 if (D.CCCIsCXX()) { 370 if (HTC.ShouldLinkCXXStdlib(Args)) 371 HTC.AddCXXStdlibLibArgs(Args, CmdArgs); 372 CmdArgs.push_back("-lm"); 373 } 374 375 CmdArgs.push_back("--start-group"); 376 377 if (!IsShared) { 378 for (StringRef Lib : OsLibs) 379 CmdArgs.push_back(Args.MakeArgString("-l" + Lib)); 380 CmdArgs.push_back("-lc"); 381 } 382 CmdArgs.push_back("-lgcc"); 383 384 CmdArgs.push_back("--end-group"); 385 } 386 387 //---------------------------------------------------------------------------- 388 // End files 389 //---------------------------------------------------------------------------- 390 if (IncStdLib && IncStartFiles) { 391 std::string Fini = UseShared 392 ? Find(RootDir, StartSubDir + "/pic", "/finiS.o") 393 : Find(RootDir, StartSubDir, "/fini.o"); 394 CmdArgs.push_back(Args.MakeArgString(Fini)); 395 } 396 } 397 398 void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, 399 const InputInfo &Output, 400 const InputInfoList &Inputs, 401 const ArgList &Args, 402 const char *LinkingOutput) const { 403 auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); 404 405 ArgStringList CmdArgs; 406 constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs, 407 LinkingOutput); 408 409 const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); 410 C.addCommand(std::make_unique<Command>( 411 JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); 412 } 413 // Hexagon tools end. 414 415 /// Hexagon Toolchain 416 417 std::string HexagonToolChain::getHexagonTargetDir( 418 const std::string &InstalledDir, 419 const SmallVectorImpl<std::string> &PrefixDirs) const { 420 std::string InstallRelDir; 421 const Driver &D = getDriver(); 422 423 // Locate the rest of the toolchain ... 424 for (auto &I : PrefixDirs) 425 if (D.getVFS().exists(I)) 426 return I; 427 428 if (getVFS().exists(InstallRelDir = InstalledDir + "/../target")) 429 return InstallRelDir; 430 431 return InstalledDir; 432 } 433 434 Optional<unsigned> HexagonToolChain::getSmallDataThreshold( 435 const ArgList &Args) { 436 StringRef Gn = ""; 437 if (Arg *A = Args.getLastArg(options::OPT_G)) { 438 Gn = A->getValue(); 439 } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, 440 options::OPT_fPIC)) { 441 Gn = "0"; 442 } 443 444 unsigned G; 445 if (!Gn.getAsInteger(10, G)) 446 return G; 447 448 return None; 449 } 450 451 void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, 452 ToolChain::path_list &LibPaths) const { 453 const Driver &D = getDriver(); 454 455 //---------------------------------------------------------------------------- 456 // -L Args 457 //---------------------------------------------------------------------------- 458 for (Arg *A : Args.filtered(options::OPT_L)) 459 for (const char *Value : A->getValues()) 460 LibPaths.push_back(Value); 461 462 //---------------------------------------------------------------------------- 463 // Other standard paths 464 //---------------------------------------------------------------------------- 465 std::vector<std::string> RootDirs; 466 std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), 467 std::back_inserter(RootDirs)); 468 469 std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), 470 D.PrefixDirs); 471 if (llvm::find(RootDirs, TargetDir) == RootDirs.end()) 472 RootDirs.push_back(TargetDir); 473 474 bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC); 475 // Assume G0 with -shared. 476 bool HasG0 = Args.hasArg(options::OPT_shared); 477 if (auto G = getSmallDataThreshold(Args)) 478 HasG0 = G.getValue() == 0; 479 480 const std::string CpuVer = GetTargetCPUVersion(Args).str(); 481 for (auto &Dir : RootDirs) { 482 std::string LibDir = Dir + "/hexagon/lib"; 483 std::string LibDirCpu = LibDir + '/' + CpuVer; 484 if (HasG0) { 485 if (HasPIC) 486 LibPaths.push_back(LibDirCpu + "/G0/pic"); 487 LibPaths.push_back(LibDirCpu + "/G0"); 488 } 489 LibPaths.push_back(LibDirCpu); 490 LibPaths.push_back(LibDir); 491 } 492 } 493 494 HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple, 495 const llvm::opt::ArgList &Args) 496 : Linux(D, Triple, Args) { 497 const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), 498 D.PrefixDirs); 499 500 // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to 501 // program paths 502 const std::string BinDir(TargetDir + "/bin"); 503 if (D.getVFS().exists(BinDir)) 504 getProgramPaths().push_back(BinDir); 505 506 ToolChain::path_list &LibPaths = getFilePaths(); 507 508 // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets 509 // 'elf' OS type, so the Linux paths are not appropriate. When we actually 510 // support 'linux' we'll need to fix this up 511 LibPaths.clear(); 512 getHexagonLibraryPaths(Args, LibPaths); 513 } 514 515 HexagonToolChain::~HexagonToolChain() {} 516 517 void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 518 ArgStringList &CmdArgs) const { 519 CXXStdlibType Type = GetCXXStdlibType(Args); 520 switch (Type) { 521 case ToolChain::CST_Libcxx: 522 CmdArgs.push_back("-lc++"); 523 CmdArgs.push_back("-lc++abi"); 524 CmdArgs.push_back("-lunwind"); 525 break; 526 527 case ToolChain::CST_Libstdcxx: 528 CmdArgs.push_back("-lstdc++"); 529 break; 530 } 531 } 532 533 Tool *HexagonToolChain::buildAssembler() const { 534 return new tools::hexagon::Assembler(*this); 535 } 536 537 Tool *HexagonToolChain::buildLinker() const { 538 return new tools::hexagon::Linker(*this); 539 } 540 541 unsigned HexagonToolChain::getOptimizationLevel( 542 const llvm::opt::ArgList &DriverArgs) const { 543 // Copied in large part from lib/Frontend/CompilerInvocation.cpp. 544 Arg *A = DriverArgs.getLastArg(options::OPT_O_Group); 545 if (!A) 546 return 0; 547 548 if (A->getOption().matches(options::OPT_O0)) 549 return 0; 550 if (A->getOption().matches(options::OPT_Ofast) || 551 A->getOption().matches(options::OPT_O4)) 552 return 3; 553 assert(A->getNumValues() != 0); 554 StringRef S(A->getValue()); 555 if (S == "s" || S == "z" || S.empty()) 556 return 2; 557 if (S == "g") 558 return 1; 559 560 unsigned OptLevel; 561 if (S.getAsInteger(10, OptLevel)) 562 return 0; 563 return OptLevel; 564 } 565 566 void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs, 567 ArgStringList &CC1Args, 568 Action::OffloadKind) const { 569 570 bool UseInitArrayDefault = getTriple().isMusl(); 571 572 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, 573 options::OPT_fno_use_init_array, 574 UseInitArrayDefault)) 575 CC1Args.push_back("-fno-use-init-array"); 576 577 if (DriverArgs.hasArg(options::OPT_ffixed_r19)) { 578 CC1Args.push_back("-target-feature"); 579 CC1Args.push_back("+reserved-r19"); 580 } 581 if (isAutoHVXEnabled(DriverArgs)) { 582 CC1Args.push_back("-mllvm"); 583 CC1Args.push_back("-hexagon-autohvx"); 584 } 585 } 586 587 void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 588 ArgStringList &CC1Args) const { 589 if (DriverArgs.hasArg(options::OPT_nostdinc) || 590 DriverArgs.hasArg(options::OPT_nostdlibinc)) 591 return; 592 593 const Driver &D = getDriver(); 594 if (!D.SysRoot.empty()) { 595 SmallString<128> P(D.SysRoot); 596 if (getTriple().isMusl()) 597 llvm::sys::path::append(P, "usr/include"); 598 else 599 llvm::sys::path::append(P, "include"); 600 addExternCSystemInclude(DriverArgs, CC1Args, P.str()); 601 return; 602 } 603 604 std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), 605 D.PrefixDirs); 606 addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include"); 607 } 608 609 void HexagonToolChain::addLibCxxIncludePaths( 610 const llvm::opt::ArgList &DriverArgs, 611 llvm::opt::ArgStringList &CC1Args) const { 612 const Driver &D = getDriver(); 613 if (!D.SysRoot.empty() && getTriple().isMusl()) 614 addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "", 615 "", DriverArgs, CC1Args); 616 else if (getTriple().isMusl()) 617 addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "", 618 DriverArgs, CC1Args); 619 else { 620 std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); 621 addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "", 622 "", DriverArgs, CC1Args); 623 } 624 } 625 void HexagonToolChain::addLibStdCxxIncludePaths( 626 const llvm::opt::ArgList &DriverArgs, 627 llvm::opt::ArgStringList &CC1Args) const { 628 const Driver &D = getDriver(); 629 std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); 630 addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "", 631 DriverArgs, CC1Args); 632 } 633 634 ToolChain::CXXStdlibType 635 HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const { 636 Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); 637 if (!A) { 638 if (getTriple().isMusl()) 639 return ToolChain::CST_Libcxx; 640 else 641 return ToolChain::CST_Libstdcxx; 642 } 643 StringRef Value = A->getValue(); 644 if (Value != "libstdc++" && Value != "libc++") 645 getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); 646 647 if (Value == "libstdc++") 648 return ToolChain::CST_Libstdcxx; 649 else if (Value == "libc++") 650 return ToolChain::CST_Libcxx; 651 else 652 return ToolChain::CST_Libstdcxx; 653 } 654 655 bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) { 656 if (Arg *A = Args.getLastArg(options::OPT_fvectorize, 657 options::OPT_fno_vectorize)) 658 return A->getOption().matches(options::OPT_fvectorize); 659 return false; 660 } 661 662 // 663 // Returns the default CPU for Hexagon. This is the default compilation target 664 // if no Hexagon processor is selected at the command-line. 665 // 666 const StringRef HexagonToolChain::GetDefaultCPU() { 667 return "hexagonv60"; 668 } 669 670 const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) { 671 Arg *CpuArg = nullptr; 672 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 673 CpuArg = A; 674 675 StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU(); 676 if (CPU.startswith("hexagon")) 677 return CPU.substr(sizeof("hexagon") - 1); 678 return CPU; 679 } 680