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