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