1 //===- ToolChain.cpp - Collections of tools for one platform --------------===// 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 "clang/Driver/ToolChain.h" 10 #include "InputInfo.h" 11 #include "ToolChains/Arch/ARM.h" 12 #include "ToolChains/Clang.h" 13 #include "ToolChains/InterfaceStubs.h" 14 #include "ToolChains/Flang.h" 15 #include "clang/Basic/ObjCRuntime.h" 16 #include "clang/Basic/Sanitizers.h" 17 #include "clang/Config/config.h" 18 #include "clang/Driver/Action.h" 19 #include "clang/Driver/Driver.h" 20 #include "clang/Driver/DriverDiagnostic.h" 21 #include "clang/Driver/Job.h" 22 #include "clang/Driver/Options.h" 23 #include "clang/Driver/SanitizerArgs.h" 24 #include "clang/Driver/XRayArgs.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/ADT/SmallString.h" 27 #include "llvm/ADT/StringRef.h" 28 #include "llvm/ADT/Triple.h" 29 #include "llvm/ADT/Twine.h" 30 #include "llvm/Config/llvm-config.h" 31 #include "llvm/MC/MCTargetOptions.h" 32 #include "llvm/Option/Arg.h" 33 #include "llvm/Option/ArgList.h" 34 #include "llvm/Option/OptTable.h" 35 #include "llvm/Option/Option.h" 36 #include "llvm/Support/ErrorHandling.h" 37 #include "llvm/Support/FileSystem.h" 38 #include "llvm/Support/Path.h" 39 #include "llvm/Support/TargetParser.h" 40 #include "llvm/Support/TargetRegistry.h" 41 #include "llvm/Support/VersionTuple.h" 42 #include "llvm/Support/VirtualFileSystem.h" 43 #include <cassert> 44 #include <cstddef> 45 #include <cstring> 46 #include <string> 47 48 using namespace clang; 49 using namespace driver; 50 using namespace tools; 51 using namespace llvm; 52 using namespace llvm::opt; 53 54 static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) { 55 return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext, 56 options::OPT_fno_rtti, options::OPT_frtti); 57 } 58 59 static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args, 60 const llvm::Triple &Triple, 61 const Arg *CachedRTTIArg) { 62 // Explicit rtti/no-rtti args 63 if (CachedRTTIArg) { 64 if (CachedRTTIArg->getOption().matches(options::OPT_frtti)) 65 return ToolChain::RM_Enabled; 66 else 67 return ToolChain::RM_Disabled; 68 } 69 70 // -frtti is default, except for the PS4 CPU. 71 return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled; 72 } 73 74 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, 75 const ArgList &Args) 76 : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), 77 CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) { 78 if (auto StdlibPath = getStdlibPath()) 79 getFilePaths().push_back(*StdlibPath); 80 81 if (auto RuntimePath = getRuntimePath()) 82 getLibraryPaths().push_back(*RuntimePath); 83 84 std::string CandidateLibPath = getArchSpecificLibPath(); 85 if (getVFS().exists(CandidateLibPath)) 86 getFilePaths().push_back(CandidateLibPath); 87 } 88 89 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { 90 Triple.setEnvironment(Env); 91 if (EffectiveTriple != llvm::Triple()) 92 EffectiveTriple.setEnvironment(Env); 93 } 94 95 ToolChain::~ToolChain() = default; 96 97 llvm::vfs::FileSystem &ToolChain::getVFS() const { 98 return getDriver().getVFS(); 99 } 100 101 bool ToolChain::useIntegratedAs() const { 102 return Args.hasFlag(options::OPT_fintegrated_as, 103 options::OPT_fno_integrated_as, 104 IsIntegratedAssemblerDefault()); 105 } 106 107 bool ToolChain::useRelaxRelocations() const { 108 return ENABLE_X86_RELAX_RELOCATIONS; 109 } 110 111 bool ToolChain::isNoExecStackDefault() const { 112 return false; 113 } 114 115 const SanitizerArgs& ToolChain::getSanitizerArgs() const { 116 if (!SanitizerArguments.get()) 117 SanitizerArguments.reset(new SanitizerArgs(*this, Args)); 118 return *SanitizerArguments.get(); 119 } 120 121 const XRayArgs& ToolChain::getXRayArgs() const { 122 if (!XRayArguments.get()) 123 XRayArguments.reset(new XRayArgs(*this, Args)); 124 return *XRayArguments.get(); 125 } 126 127 namespace { 128 129 struct DriverSuffix { 130 const char *Suffix; 131 const char *ModeFlag; 132 }; 133 134 } // namespace 135 136 static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { 137 // A list of known driver suffixes. Suffixes are compared against the 138 // program name in order. If there is a match, the frontend type is updated as 139 // necessary by applying the ModeFlag. 140 static const DriverSuffix DriverSuffixes[] = { 141 {"clang", nullptr}, 142 {"clang++", "--driver-mode=g++"}, 143 {"clang-c++", "--driver-mode=g++"}, 144 {"clang-cc", nullptr}, 145 {"clang-cpp", "--driver-mode=cpp"}, 146 {"clang-g++", "--driver-mode=g++"}, 147 {"clang-gcc", nullptr}, 148 {"clang-cl", "--driver-mode=cl"}, 149 {"cc", nullptr}, 150 {"cpp", "--driver-mode=cpp"}, 151 {"cl", "--driver-mode=cl"}, 152 {"++", "--driver-mode=g++"}, 153 {"flang", "--driver-mode=flang"}, 154 }; 155 156 for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) { 157 StringRef Suffix(DriverSuffixes[i].Suffix); 158 if (ProgName.endswith(Suffix)) { 159 Pos = ProgName.size() - Suffix.size(); 160 return &DriverSuffixes[i]; 161 } 162 } 163 return nullptr; 164 } 165 166 /// Normalize the program name from argv[0] by stripping the file extension if 167 /// present and lower-casing the string on Windows. 168 static std::string normalizeProgramName(llvm::StringRef Argv0) { 169 std::string ProgName = std::string(llvm::sys::path::stem(Argv0)); 170 #ifdef _WIN32 171 // Transform to lowercase for case insensitive file systems. 172 std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower); 173 #endif 174 return ProgName; 175 } 176 177 static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) { 178 // Try to infer frontend type and default target from the program name by 179 // comparing it against DriverSuffixes in order. 180 181 // If there is a match, the function tries to identify a target as prefix. 182 // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target 183 // prefix "x86_64-linux". If such a target prefix is found, it may be 184 // added via -target as implicit first argument. 185 const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos); 186 187 if (!DS) { 188 // Try again after stripping any trailing version number: 189 // clang++3.5 -> clang++ 190 ProgName = ProgName.rtrim("0123456789."); 191 DS = FindDriverSuffix(ProgName, Pos); 192 } 193 194 if (!DS) { 195 // Try again after stripping trailing -component. 196 // clang++-tot -> clang++ 197 ProgName = ProgName.slice(0, ProgName.rfind('-')); 198 DS = FindDriverSuffix(ProgName, Pos); 199 } 200 return DS; 201 } 202 203 ParsedClangName 204 ToolChain::getTargetAndModeFromProgramName(StringRef PN) { 205 std::string ProgName = normalizeProgramName(PN); 206 size_t SuffixPos; 207 const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos); 208 if (!DS) 209 return {}; 210 size_t SuffixEnd = SuffixPos + strlen(DS->Suffix); 211 212 size_t LastComponent = ProgName.rfind('-', SuffixPos); 213 if (LastComponent == std::string::npos) 214 return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag); 215 std::string ModeSuffix = ProgName.substr(LastComponent + 1, 216 SuffixEnd - LastComponent - 1); 217 218 // Infer target from the prefix. 219 StringRef Prefix(ProgName); 220 Prefix = Prefix.slice(0, LastComponent); 221 std::string IgnoredError; 222 bool IsRegistered = 223 llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError); 224 return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag, 225 IsRegistered}; 226 } 227 228 StringRef ToolChain::getDefaultUniversalArchName() const { 229 // In universal driver terms, the arch name accepted by -arch isn't exactly 230 // the same as the ones that appear in the triple. Roughly speaking, this is 231 // an inverse of the darwin::getArchTypeForDarwinArchName() function. 232 switch (Triple.getArch()) { 233 case llvm::Triple::aarch64: { 234 if (getTriple().isArm64e()) 235 return "arm64e"; 236 return "arm64"; 237 } 238 case llvm::Triple::aarch64_32: 239 return "arm64_32"; 240 case llvm::Triple::ppc: 241 return "ppc"; 242 case llvm::Triple::ppcle: 243 return "ppcle"; 244 case llvm::Triple::ppc64: 245 return "ppc64"; 246 case llvm::Triple::ppc64le: 247 return "ppc64le"; 248 default: 249 return Triple.getArchName(); 250 } 251 } 252 253 std::string ToolChain::getInputFilename(const InputInfo &Input) const { 254 return Input.getFilename(); 255 } 256 257 bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const { 258 return false; 259 } 260 261 Tool *ToolChain::getClang() const { 262 if (!Clang) 263 Clang.reset(new tools::Clang(*this)); 264 return Clang.get(); 265 } 266 267 Tool *ToolChain::getFlang() const { 268 if (!Flang) 269 Flang.reset(new tools::Flang(*this)); 270 return Flang.get(); 271 } 272 273 Tool *ToolChain::buildAssembler() const { 274 return new tools::ClangAs(*this); 275 } 276 277 Tool *ToolChain::buildLinker() const { 278 llvm_unreachable("Linking is not supported by this toolchain"); 279 } 280 281 Tool *ToolChain::buildStaticLibTool() const { 282 llvm_unreachable("Creating static lib is not supported by this toolchain"); 283 } 284 285 Tool *ToolChain::getAssemble() const { 286 if (!Assemble) 287 Assemble.reset(buildAssembler()); 288 return Assemble.get(); 289 } 290 291 Tool *ToolChain::getClangAs() const { 292 if (!Assemble) 293 Assemble.reset(new tools::ClangAs(*this)); 294 return Assemble.get(); 295 } 296 297 Tool *ToolChain::getLink() const { 298 if (!Link) 299 Link.reset(buildLinker()); 300 return Link.get(); 301 } 302 303 Tool *ToolChain::getStaticLibTool() const { 304 if (!StaticLibTool) 305 StaticLibTool.reset(buildStaticLibTool()); 306 return StaticLibTool.get(); 307 } 308 309 Tool *ToolChain::getIfsMerge() const { 310 if (!IfsMerge) 311 IfsMerge.reset(new tools::ifstool::Merger(*this)); 312 return IfsMerge.get(); 313 } 314 315 Tool *ToolChain::getOffloadBundler() const { 316 if (!OffloadBundler) 317 OffloadBundler.reset(new tools::OffloadBundler(*this)); 318 return OffloadBundler.get(); 319 } 320 321 Tool *ToolChain::getOffloadWrapper() const { 322 if (!OffloadWrapper) 323 OffloadWrapper.reset(new tools::OffloadWrapper(*this)); 324 return OffloadWrapper.get(); 325 } 326 327 Tool *ToolChain::getTool(Action::ActionClass AC) const { 328 switch (AC) { 329 case Action::AssembleJobClass: 330 return getAssemble(); 331 332 case Action::IfsMergeJobClass: 333 return getIfsMerge(); 334 335 case Action::LinkJobClass: 336 return getLink(); 337 338 case Action::StaticLibJobClass: 339 return getStaticLibTool(); 340 341 case Action::InputClass: 342 case Action::BindArchClass: 343 case Action::OffloadClass: 344 case Action::LipoJobClass: 345 case Action::DsymutilJobClass: 346 case Action::VerifyDebugInfoJobClass: 347 llvm_unreachable("Invalid tool kind."); 348 349 case Action::CompileJobClass: 350 case Action::PrecompileJobClass: 351 case Action::HeaderModulePrecompileJobClass: 352 case Action::PreprocessJobClass: 353 case Action::AnalyzeJobClass: 354 case Action::MigrateJobClass: 355 case Action::VerifyPCHJobClass: 356 case Action::BackendJobClass: 357 return getClang(); 358 359 case Action::OffloadBundlingJobClass: 360 case Action::OffloadUnbundlingJobClass: 361 return getOffloadBundler(); 362 363 case Action::OffloadWrapperJobClass: 364 return getOffloadWrapper(); 365 } 366 367 llvm_unreachable("Invalid tool kind."); 368 } 369 370 static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, 371 const ArgList &Args) { 372 const llvm::Triple &Triple = TC.getTriple(); 373 bool IsWindows = Triple.isOSWindows(); 374 375 if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb) 376 return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows) 377 ? "armhf" 378 : "arm"; 379 380 // For historic reasons, Android library is using i686 instead of i386. 381 if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid()) 382 return "i686"; 383 384 return llvm::Triple::getArchTypeName(TC.getArch()); 385 } 386 387 StringRef ToolChain::getOSLibName() const { 388 switch (Triple.getOS()) { 389 case llvm::Triple::FreeBSD: 390 return "freebsd"; 391 case llvm::Triple::NetBSD: 392 return "netbsd"; 393 case llvm::Triple::OpenBSD: 394 return "openbsd"; 395 case llvm::Triple::Solaris: 396 return "sunos"; 397 case llvm::Triple::AIX: 398 return "aix"; 399 default: 400 return getOS(); 401 } 402 } 403 404 std::string ToolChain::getCompilerRTPath() const { 405 SmallString<128> Path(getDriver().ResourceDir); 406 if (Triple.isOSUnknown()) { 407 llvm::sys::path::append(Path, "lib"); 408 } else { 409 llvm::sys::path::append(Path, "lib", getOSLibName()); 410 } 411 return std::string(Path.str()); 412 } 413 414 std::string ToolChain::getCompilerRTBasename(const ArgList &Args, 415 StringRef Component, 416 FileType Type) const { 417 std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type); 418 return llvm::sys::path::filename(CRTAbsolutePath).str(); 419 } 420 421 std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args, 422 StringRef Component, 423 FileType Type, 424 bool AddArch) const { 425 const llvm::Triple &TT = getTriple(); 426 bool IsITANMSVCWindows = 427 TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); 428 429 const char *Prefix = 430 IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib"; 431 const char *Suffix; 432 switch (Type) { 433 case ToolChain::FT_Object: 434 Suffix = IsITANMSVCWindows ? ".obj" : ".o"; 435 break; 436 case ToolChain::FT_Static: 437 Suffix = IsITANMSVCWindows ? ".lib" : ".a"; 438 break; 439 case ToolChain::FT_Shared: 440 Suffix = TT.isOSWindows() 441 ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib") 442 : ".so"; 443 break; 444 } 445 446 std::string ArchAndEnv; 447 if (AddArch) { 448 StringRef Arch = getArchNameForCompilerRTLib(*this, Args); 449 const char *Env = TT.isAndroid() ? "-android" : ""; 450 ArchAndEnv = ("-" + Arch + Env).str(); 451 } 452 return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str(); 453 } 454 455 std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, 456 FileType Type) const { 457 // Check for runtime files in the new layout without the architecture first. 458 std::string CRTBasename = 459 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false); 460 for (const auto &LibPath : getLibraryPaths()) { 461 SmallString<128> P(LibPath); 462 llvm::sys::path::append(P, CRTBasename); 463 if (getVFS().exists(P)) 464 return std::string(P.str()); 465 } 466 467 // Fall back to the old expected compiler-rt name if the new one does not 468 // exist. 469 CRTBasename = 470 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true); 471 SmallString<128> Path(getCompilerRTPath()); 472 llvm::sys::path::append(Path, CRTBasename); 473 return std::string(Path.str()); 474 } 475 476 const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, 477 StringRef Component, 478 FileType Type) const { 479 return Args.MakeArgString(getCompilerRT(Args, Component, Type)); 480 } 481 482 483 Optional<std::string> ToolChain::getRuntimePath() const { 484 SmallString<128> P; 485 486 // First try the triple passed to driver as --target=<triple>. 487 P.assign(D.ResourceDir); 488 llvm::sys::path::append(P, "lib", D.getTargetTriple()); 489 if (getVFS().exists(P)) 490 return llvm::Optional<std::string>(std::string(P.str())); 491 492 // Second try the normalized triple. 493 P.assign(D.ResourceDir); 494 llvm::sys::path::append(P, "lib", Triple.str()); 495 if (getVFS().exists(P)) 496 return llvm::Optional<std::string>(std::string(P.str())); 497 498 return None; 499 } 500 501 Optional<std::string> ToolChain::getStdlibPath() const { 502 SmallString<128> P; 503 504 // First try the triple passed to driver as --target=<triple>. 505 P.assign(D.Dir); 506 llvm::sys::path::append(P, "..", "lib", D.getTargetTriple()); 507 if (getVFS().exists(P)) 508 return llvm::Optional<std::string>(std::string(P.str())); 509 510 // Second try the normalized triple. 511 P.assign(D.Dir); 512 llvm::sys::path::append(P, "..", "lib", Triple.str()); 513 if (getVFS().exists(P)) 514 return llvm::Optional<std::string>(std::string(P.str())); 515 516 return None; 517 } 518 519 std::string ToolChain::getArchSpecificLibPath() const { 520 SmallString<128> Path(getDriver().ResourceDir); 521 llvm::sys::path::append(Path, "lib", getOSLibName(), 522 llvm::Triple::getArchTypeName(getArch())); 523 return std::string(Path.str()); 524 } 525 526 bool ToolChain::needsProfileRT(const ArgList &Args) { 527 if (Args.hasArg(options::OPT_noprofilelib)) 528 return false; 529 530 return Args.hasArg(options::OPT_fprofile_generate) || 531 Args.hasArg(options::OPT_fprofile_generate_EQ) || 532 Args.hasArg(options::OPT_fcs_profile_generate) || 533 Args.hasArg(options::OPT_fcs_profile_generate_EQ) || 534 Args.hasArg(options::OPT_fprofile_instr_generate) || 535 Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || 536 Args.hasArg(options::OPT_fcreate_profile) || 537 Args.hasArg(options::OPT_forder_file_instrumentation); 538 } 539 540 bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { 541 return Args.hasArg(options::OPT_coverage) || 542 Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 543 false); 544 } 545 546 Tool *ToolChain::SelectTool(const JobAction &JA) const { 547 if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang(); 548 if (getDriver().ShouldUseClangCompiler(JA)) return getClang(); 549 Action::ActionClass AC = JA.getKind(); 550 if (AC == Action::AssembleJobClass && useIntegratedAs()) 551 return getClangAs(); 552 return getTool(AC); 553 } 554 555 std::string ToolChain::GetFilePath(const char *Name) const { 556 return D.GetFilePath(Name, *this); 557 } 558 559 std::string ToolChain::GetProgramPath(const char *Name) const { 560 return D.GetProgramPath(Name, *this); 561 } 562 563 std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD, 564 bool *LinkerIsLLDDarwinNew) const { 565 if (LinkerIsLLD) 566 *LinkerIsLLD = false; 567 if (LinkerIsLLDDarwinNew) 568 *LinkerIsLLDDarwinNew = false; 569 570 // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is 571 // considered as the linker flavor, e.g. "bfd", "gold", or "lld". 572 const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ); 573 StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER; 574 575 // --ld-path= takes precedence over -fuse-ld= and specifies the executable 576 // name. -B, COMPILER_PATH and PATH and consulted if the value does not 577 // contain a path component separator. 578 if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) { 579 std::string Path(A->getValue()); 580 if (!Path.empty()) { 581 if (llvm::sys::path::parent_path(Path).empty()) 582 Path = GetProgramPath(A->getValue()); 583 if (llvm::sys::fs::can_execute(Path)) 584 return std::string(Path); 585 } 586 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); 587 return GetProgramPath(getDefaultLinker()); 588 } 589 // If we're passed -fuse-ld= with no argument, or with the argument ld, 590 // then use whatever the default system linker is. 591 if (UseLinker.empty() || UseLinker == "ld") { 592 const char *DefaultLinker = getDefaultLinker(); 593 if (llvm::sys::path::is_absolute(DefaultLinker)) 594 return std::string(DefaultLinker); 595 else 596 return GetProgramPath(DefaultLinker); 597 } 598 599 // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking 600 // for the linker flavor is brittle. In addition, prepending "ld." or "ld64." 601 // to a relative path is surprising. This is more complex due to priorities 602 // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead. 603 if (UseLinker.find('/') != StringRef::npos) 604 getDriver().Diag(diag::warn_drv_fuse_ld_path); 605 606 if (llvm::sys::path::is_absolute(UseLinker)) { 607 // If we're passed what looks like an absolute path, don't attempt to 608 // second-guess that. 609 if (llvm::sys::fs::can_execute(UseLinker)) 610 return std::string(UseLinker); 611 } else { 612 llvm::SmallString<8> LinkerName; 613 if (Triple.isOSDarwin()) 614 LinkerName.append("ld64."); 615 else 616 LinkerName.append("ld."); 617 LinkerName.append(UseLinker); 618 619 std::string LinkerPath(GetProgramPath(LinkerName.c_str())); 620 if (llvm::sys::fs::can_execute(LinkerPath)) { 621 // FIXME: Remove LinkerIsLLDDarwinNew once there's only one MachO lld. 622 if (LinkerIsLLD) 623 *LinkerIsLLD = UseLinker == "lld" || UseLinker == "lld.darwinold"; 624 if (LinkerIsLLDDarwinNew) 625 *LinkerIsLLDDarwinNew = UseLinker == "lld"; 626 return LinkerPath; 627 } 628 } 629 630 if (A) 631 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); 632 633 return GetProgramPath(getDefaultLinker()); 634 } 635 636 std::string ToolChain::GetStaticLibToolPath() const { 637 // TODO: Add support for static lib archiving on Windows 638 return GetProgramPath("llvm-ar"); 639 } 640 641 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { 642 types::ID id = types::lookupTypeForExtension(Ext); 643 644 // Flang always runs the preprocessor and has no notion of "preprocessed 645 // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating 646 // them differently. 647 if (D.IsFlangMode() && id == types::TY_PP_Fortran) 648 id = types::TY_Fortran; 649 650 return id; 651 } 652 653 bool ToolChain::HasNativeLLVMSupport() const { 654 return false; 655 } 656 657 bool ToolChain::isCrossCompiling() const { 658 llvm::Triple HostTriple(LLVM_HOST_TRIPLE); 659 switch (HostTriple.getArch()) { 660 // The A32/T32/T16 instruction sets are not separate architectures in this 661 // context. 662 case llvm::Triple::arm: 663 case llvm::Triple::armeb: 664 case llvm::Triple::thumb: 665 case llvm::Triple::thumbeb: 666 return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb && 667 getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb; 668 default: 669 return HostTriple.getArch() != getArch(); 670 } 671 } 672 673 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { 674 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC, 675 VersionTuple()); 676 } 677 678 llvm::ExceptionHandling 679 ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const { 680 return llvm::ExceptionHandling::None; 681 } 682 683 bool ToolChain::isThreadModelSupported(const StringRef Model) const { 684 if (Model == "single") { 685 // FIXME: 'single' is only supported on ARM and WebAssembly so far. 686 return Triple.getArch() == llvm::Triple::arm || 687 Triple.getArch() == llvm::Triple::armeb || 688 Triple.getArch() == llvm::Triple::thumb || 689 Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm(); 690 } else if (Model == "posix") 691 return true; 692 693 return false; 694 } 695 696 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, 697 types::ID InputType) const { 698 switch (getTriple().getArch()) { 699 default: 700 return getTripleString(); 701 702 case llvm::Triple::x86_64: { 703 llvm::Triple Triple = getTriple(); 704 if (!Triple.isOSBinFormatMachO()) 705 return getTripleString(); 706 707 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 708 // x86_64h goes in the triple. Other -march options just use the 709 // vanilla triple we already have. 710 StringRef MArch = A->getValue(); 711 if (MArch == "x86_64h") 712 Triple.setArchName(MArch); 713 } 714 return Triple.getTriple(); 715 } 716 case llvm::Triple::aarch64: { 717 llvm::Triple Triple = getTriple(); 718 if (!Triple.isOSBinFormatMachO()) 719 return getTripleString(); 720 721 if (Triple.isArm64e()) 722 return getTripleString(); 723 724 // FIXME: older versions of ld64 expect the "arm64" component in the actual 725 // triple string and query it to determine whether an LTO file can be 726 // handled. Remove this when we don't care any more. 727 Triple.setArchName("arm64"); 728 return Triple.getTriple(); 729 } 730 case llvm::Triple::aarch64_32: 731 return getTripleString(); 732 case llvm::Triple::arm: 733 case llvm::Triple::armeb: 734 case llvm::Triple::thumb: 735 case llvm::Triple::thumbeb: { 736 llvm::Triple Triple = getTriple(); 737 tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple); 738 tools::arm::setFloatABIInTriple(getDriver(), Args, Triple); 739 return Triple.getTriple(); 740 } 741 } 742 } 743 744 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 745 types::ID InputType) const { 746 return ComputeLLVMTriple(Args, InputType); 747 } 748 749 std::string ToolChain::computeSysRoot() const { 750 return D.SysRoot; 751 } 752 753 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 754 ArgStringList &CC1Args) const { 755 // Each toolchain should provide the appropriate include flags. 756 } 757 758 void ToolChain::addClangTargetOptions( 759 const ArgList &DriverArgs, ArgStringList &CC1Args, 760 Action::OffloadKind DeviceOffloadKind) const {} 761 762 void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} 763 764 void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args, 765 llvm::opt::ArgStringList &CmdArgs) const { 766 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)) 767 return; 768 769 CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); 770 } 771 772 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( 773 const ArgList &Args) const { 774 if (runtimeLibType) 775 return *runtimeLibType; 776 777 const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ); 778 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB; 779 780 // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB! 781 if (LibName == "compiler-rt") 782 runtimeLibType = ToolChain::RLT_CompilerRT; 783 else if (LibName == "libgcc") 784 runtimeLibType = ToolChain::RLT_Libgcc; 785 else if (LibName == "platform") 786 runtimeLibType = GetDefaultRuntimeLibType(); 787 else { 788 if (A) 789 getDriver().Diag(diag::err_drv_invalid_rtlib_name) 790 << A->getAsString(Args); 791 792 runtimeLibType = GetDefaultRuntimeLibType(); 793 } 794 795 return *runtimeLibType; 796 } 797 798 ToolChain::UnwindLibType ToolChain::GetUnwindLibType( 799 const ArgList &Args) const { 800 if (unwindLibType) 801 return *unwindLibType; 802 803 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); 804 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB; 805 806 if (LibName == "none") 807 unwindLibType = ToolChain::UNW_None; 808 else if (LibName == "platform" || LibName == "") { 809 ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); 810 if (RtLibType == ToolChain::RLT_CompilerRT) { 811 if (getTriple().isAndroid()) 812 unwindLibType = ToolChain::UNW_CompilerRT; 813 else 814 unwindLibType = ToolChain::UNW_None; 815 } else if (RtLibType == ToolChain::RLT_Libgcc) 816 unwindLibType = ToolChain::UNW_Libgcc; 817 } else if (LibName == "libunwind") { 818 if (GetRuntimeLibType(Args) == RLT_Libgcc) 819 getDriver().Diag(diag::err_drv_incompatible_unwindlib); 820 unwindLibType = ToolChain::UNW_CompilerRT; 821 } else if (LibName == "libgcc") 822 unwindLibType = ToolChain::UNW_Libgcc; 823 else { 824 if (A) 825 getDriver().Diag(diag::err_drv_invalid_unwindlib_name) 826 << A->getAsString(Args); 827 828 unwindLibType = GetDefaultUnwindLibType(); 829 } 830 831 return *unwindLibType; 832 } 833 834 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ 835 if (cxxStdlibType) 836 return *cxxStdlibType; 837 838 const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); 839 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB; 840 841 // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB! 842 if (LibName == "libc++") 843 cxxStdlibType = ToolChain::CST_Libcxx; 844 else if (LibName == "libstdc++") 845 cxxStdlibType = ToolChain::CST_Libstdcxx; 846 else if (LibName == "platform") 847 cxxStdlibType = GetDefaultCXXStdlibType(); 848 else { 849 if (A) 850 getDriver().Diag(diag::err_drv_invalid_stdlib_name) 851 << A->getAsString(Args); 852 853 cxxStdlibType = GetDefaultCXXStdlibType(); 854 } 855 856 return *cxxStdlibType; 857 } 858 859 /// Utility function to add a system include directory to CC1 arguments. 860 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, 861 ArgStringList &CC1Args, 862 const Twine &Path) { 863 CC1Args.push_back("-internal-isystem"); 864 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 865 } 866 867 /// Utility function to add a system include directory with extern "C" 868 /// semantics to CC1 arguments. 869 /// 870 /// Note that this should be used rarely, and only for directories that 871 /// historically and for legacy reasons are treated as having implicit extern 872 /// "C" semantics. These semantics are *ignored* by and large today, but its 873 /// important to preserve the preprocessor changes resulting from the 874 /// classification. 875 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, 876 ArgStringList &CC1Args, 877 const Twine &Path) { 878 CC1Args.push_back("-internal-externc-isystem"); 879 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 880 } 881 882 void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs, 883 ArgStringList &CC1Args, 884 const Twine &Path) { 885 if (llvm::sys::fs::exists(Path)) 886 addExternCSystemInclude(DriverArgs, CC1Args, Path); 887 } 888 889 /// Utility function to add a list of system include directories to CC1. 890 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, 891 ArgStringList &CC1Args, 892 ArrayRef<StringRef> Paths) { 893 for (const auto &Path : Paths) { 894 CC1Args.push_back("-internal-isystem"); 895 CC1Args.push_back(DriverArgs.MakeArgString(Path)); 896 } 897 } 898 899 std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const { 900 std::error_code EC; 901 int MaxVersion = 0; 902 std::string MaxVersionString; 903 SmallString<128> Path(IncludePath); 904 llvm::sys::path::append(Path, "c++"); 905 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE; 906 !EC && LI != LE; LI = LI.increment(EC)) { 907 StringRef VersionText = llvm::sys::path::filename(LI->path()); 908 int Version; 909 if (VersionText[0] == 'v' && 910 !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) { 911 if (Version > MaxVersion) { 912 MaxVersion = Version; 913 MaxVersionString = std::string(VersionText); 914 } 915 } 916 } 917 if (!MaxVersion) 918 return ""; 919 return MaxVersionString; 920 } 921 922 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 923 ArgStringList &CC1Args) const { 924 // Header search paths should be handled by each of the subclasses. 925 // Historically, they have not been, and instead have been handled inside of 926 // the CC1-layer frontend. As the logic is hoisted out, this generic function 927 // will slowly stop being called. 928 // 929 // While it is being called, replicate a bit of a hack to propagate the 930 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ 931 // header search paths with it. Once all systems are overriding this 932 // function, the CC1 flag and this line can be removed. 933 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); 934 } 935 936 void ToolChain::AddClangCXXStdlibIsystemArgs( 937 const llvm::opt::ArgList &DriverArgs, 938 llvm::opt::ArgStringList &CC1Args) const { 939 DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem); 940 if (!DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx, 941 options::OPT_nostdlibinc)) 942 for (const auto &P : 943 DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem)) 944 addSystemInclude(DriverArgs, CC1Args, P); 945 } 946 947 bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const { 948 return getDriver().CCCIsCXX() && 949 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 950 options::OPT_nostdlibxx); 951 } 952 953 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 954 ArgStringList &CmdArgs) const { 955 assert(!Args.hasArg(options::OPT_nostdlibxx) && 956 "should not have called this"); 957 CXXStdlibType Type = GetCXXStdlibType(Args); 958 959 switch (Type) { 960 case ToolChain::CST_Libcxx: 961 CmdArgs.push_back("-lc++"); 962 break; 963 964 case ToolChain::CST_Libstdcxx: 965 CmdArgs.push_back("-lstdc++"); 966 break; 967 } 968 } 969 970 void ToolChain::AddFilePathLibArgs(const ArgList &Args, 971 ArgStringList &CmdArgs) const { 972 for (const auto &LibPath : getFilePaths()) 973 if(LibPath.length() > 0) 974 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); 975 } 976 977 void ToolChain::AddCCKextLibArgs(const ArgList &Args, 978 ArgStringList &CmdArgs) const { 979 CmdArgs.push_back("-lcc_kext"); 980 } 981 982 bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, 983 std::string &Path) const { 984 // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed 985 // (to keep the linker options consistent with gcc and clang itself). 986 if (!isOptimizationLevelFast(Args)) { 987 // Check if -ffast-math or -funsafe-math. 988 Arg *A = 989 Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, 990 options::OPT_funsafe_math_optimizations, 991 options::OPT_fno_unsafe_math_optimizations); 992 993 if (!A || A->getOption().getID() == options::OPT_fno_fast_math || 994 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) 995 return false; 996 } 997 // If crtfastmath.o exists add it to the arguments. 998 Path = GetFilePath("crtfastmath.o"); 999 return (Path != "crtfastmath.o"); // Not found. 1000 } 1001 1002 bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args, 1003 ArgStringList &CmdArgs) const { 1004 std::string Path; 1005 if (isFastMathRuntimeAvailable(Args, Path)) { 1006 CmdArgs.push_back(Args.MakeArgString(Path)); 1007 return true; 1008 } 1009 1010 return false; 1011 } 1012 1013 SanitizerMask ToolChain::getSupportedSanitizers() const { 1014 // Return sanitizers which don't require runtime support and are not 1015 // platform dependent. 1016 1017 SanitizerMask Res = 1018 (SanitizerKind::Undefined & ~SanitizerKind::Vptr & 1019 ~SanitizerKind::Function) | 1020 (SanitizerKind::CFI & ~SanitizerKind::CFIICall) | 1021 SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero | 1022 SanitizerKind::UnsignedIntegerOverflow | 1023 SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion | 1024 SanitizerKind::Nullability | SanitizerKind::LocalBounds; 1025 if (getTriple().getArch() == llvm::Triple::x86 || 1026 getTriple().getArch() == llvm::Triple::x86_64 || 1027 getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() || 1028 getTriple().isAArch64()) 1029 Res |= SanitizerKind::CFIICall; 1030 if (getTriple().getArch() == llvm::Triple::x86_64 || 1031 getTriple().isAArch64(64) || getTriple().isRISCV()) 1032 Res |= SanitizerKind::ShadowCallStack; 1033 if (getTriple().isAArch64(64)) 1034 Res |= SanitizerKind::MemTag; 1035 return Res; 1036 } 1037 1038 void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 1039 ArgStringList &CC1Args) const {} 1040 1041 void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 1042 ArgStringList &CC1Args) const {} 1043 1044 llvm::SmallVector<std::string, 12> 1045 ToolChain::getHIPDeviceLibs(const ArgList &DriverArgs) const { 1046 return {}; 1047 } 1048 1049 void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs, 1050 ArgStringList &CC1Args) const {} 1051 1052 static VersionTuple separateMSVCFullVersion(unsigned Version) { 1053 if (Version < 100) 1054 return VersionTuple(Version); 1055 1056 if (Version < 10000) 1057 return VersionTuple(Version / 100, Version % 100); 1058 1059 unsigned Build = 0, Factor = 1; 1060 for (; Version > 10000; Version = Version / 10, Factor = Factor * 10) 1061 Build = Build + (Version % 10) * Factor; 1062 return VersionTuple(Version / 100, Version % 100, Build); 1063 } 1064 1065 VersionTuple 1066 ToolChain::computeMSVCVersion(const Driver *D, 1067 const llvm::opt::ArgList &Args) const { 1068 const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); 1069 const Arg *MSCompatibilityVersion = 1070 Args.getLastArg(options::OPT_fms_compatibility_version); 1071 1072 if (MSCVersion && MSCompatibilityVersion) { 1073 if (D) 1074 D->Diag(diag::err_drv_argument_not_allowed_with) 1075 << MSCVersion->getAsString(Args) 1076 << MSCompatibilityVersion->getAsString(Args); 1077 return VersionTuple(); 1078 } 1079 1080 if (MSCompatibilityVersion) { 1081 VersionTuple MSVT; 1082 if (MSVT.tryParse(MSCompatibilityVersion->getValue())) { 1083 if (D) 1084 D->Diag(diag::err_drv_invalid_value) 1085 << MSCompatibilityVersion->getAsString(Args) 1086 << MSCompatibilityVersion->getValue(); 1087 } else { 1088 return MSVT; 1089 } 1090 } 1091 1092 if (MSCVersion) { 1093 unsigned Version = 0; 1094 if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) { 1095 if (D) 1096 D->Diag(diag::err_drv_invalid_value) 1097 << MSCVersion->getAsString(Args) << MSCVersion->getValue(); 1098 } else { 1099 return separateMSVCFullVersion(Version); 1100 } 1101 } 1102 1103 return VersionTuple(); 1104 } 1105 1106 llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( 1107 const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, 1108 SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const { 1109 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 1110 const OptTable &Opts = getDriver().getOpts(); 1111 bool Modified = false; 1112 1113 // Handle -Xopenmp-target flags 1114 for (auto *A : Args) { 1115 // Exclude flags which may only apply to the host toolchain. 1116 // Do not exclude flags when the host triple (AuxTriple) 1117 // matches the current toolchain triple. If it is not present 1118 // at all, target and host share a toolchain. 1119 if (A->getOption().matches(options::OPT_m_Group)) { 1120 if (SameTripleAsHost) 1121 DAL->append(A); 1122 else 1123 Modified = true; 1124 continue; 1125 } 1126 1127 unsigned Index; 1128 unsigned Prev; 1129 bool XOpenMPTargetNoTriple = 1130 A->getOption().matches(options::OPT_Xopenmp_target); 1131 1132 if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { 1133 // Passing device args: -Xopenmp-target=<triple> -opt=val. 1134 if (A->getValue(0) == getTripleString()) 1135 Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); 1136 else 1137 continue; 1138 } else if (XOpenMPTargetNoTriple) { 1139 // Passing device args: -Xopenmp-target -opt=val. 1140 Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); 1141 } else { 1142 DAL->append(A); 1143 continue; 1144 } 1145 1146 // Parse the argument to -Xopenmp-target. 1147 Prev = Index; 1148 std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); 1149 if (!XOpenMPTargetArg || Index > Prev + 1) { 1150 getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) 1151 << A->getAsString(Args); 1152 continue; 1153 } 1154 if (XOpenMPTargetNoTriple && XOpenMPTargetArg && 1155 Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) { 1156 getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); 1157 continue; 1158 } 1159 XOpenMPTargetArg->setBaseArg(A); 1160 A = XOpenMPTargetArg.release(); 1161 AllocatedArgs.push_back(A); 1162 DAL->append(A); 1163 Modified = true; 1164 } 1165 1166 if (Modified) 1167 return DAL; 1168 1169 delete DAL; 1170 return nullptr; 1171 } 1172 1173 // TODO: Currently argument values separated by space e.g. 1174 // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be 1175 // fixed. 1176 void ToolChain::TranslateXarchArgs( 1177 const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A, 1178 llvm::opt::DerivedArgList *DAL, 1179 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { 1180 const OptTable &Opts = getDriver().getOpts(); 1181 unsigned ValuePos = 1; 1182 if (A->getOption().matches(options::OPT_Xarch_device) || 1183 A->getOption().matches(options::OPT_Xarch_host)) 1184 ValuePos = 0; 1185 1186 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos)); 1187 unsigned Prev = Index; 1188 std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index)); 1189 1190 // If the argument parsing failed or more than one argument was 1191 // consumed, the -Xarch_ argument's parameter tried to consume 1192 // extra arguments. Emit an error and ignore. 1193 // 1194 // We also want to disallow any options which would alter the 1195 // driver behavior; that isn't going to work in our model. We 1196 // use options::NoXarchOption to control this. 1197 if (!XarchArg || Index > Prev + 1) { 1198 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) 1199 << A->getAsString(Args); 1200 return; 1201 } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) { 1202 auto &Diags = getDriver().getDiags(); 1203 unsigned DiagID = 1204 Diags.getCustomDiagID(DiagnosticsEngine::Error, 1205 "invalid Xarch argument: '%0', not all driver " 1206 "options can be forwared via Xarch argument"); 1207 Diags.Report(DiagID) << A->getAsString(Args); 1208 return; 1209 } 1210 XarchArg->setBaseArg(A); 1211 A = XarchArg.release(); 1212 if (!AllocatedArgs) 1213 DAL->AddSynthesizedArg(A); 1214 else 1215 AllocatedArgs->push_back(A); 1216 } 1217 1218 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs( 1219 const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 1220 Action::OffloadKind OFK, 1221 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { 1222 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 1223 bool Modified = false; 1224 1225 bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP; 1226 for (Arg *A : Args) { 1227 bool NeedTrans = false; 1228 bool Skip = false; 1229 if (A->getOption().matches(options::OPT_Xarch_device)) { 1230 NeedTrans = IsGPU; 1231 Skip = !IsGPU; 1232 } else if (A->getOption().matches(options::OPT_Xarch_host)) { 1233 NeedTrans = !IsGPU; 1234 Skip = IsGPU; 1235 } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) { 1236 // Do not translate -Xarch_ options for non CUDA/HIP toolchain since 1237 // they may need special translation. 1238 // Skip this argument unless the architecture matches BoundArch 1239 if (BoundArch.empty() || A->getValue(0) != BoundArch) 1240 Skip = true; 1241 else 1242 NeedTrans = true; 1243 } 1244 if (NeedTrans || Skip) 1245 Modified = true; 1246 if (NeedTrans) 1247 TranslateXarchArgs(Args, A, DAL, AllocatedArgs); 1248 if (!Skip) 1249 DAL->append(A); 1250 } 1251 1252 if (Modified) 1253 return DAL; 1254 1255 delete DAL; 1256 return nullptr; 1257 } 1258