static std::string getX86TargetCPU(const llvm::Triple &triple) { // Select the default CPU if none was given (or detection failed). // Intel Macs are relatively recent, take advantage of that. if (triple.isOSDarwin()) return triple.isArch64Bit() ? "core2" : "yonah"; // Everything else goes to x86-64 in 64-bit mode. if (triple.isArch64Bit()) return "x86-64"; if (triple.getOSName().startswith("haiku")) return "i586"; if (triple.getOSName().startswith("openbsd")) return "i486"; if (triple.getOSName().startswith("bitrig")) return "i686"; if (triple.getOSName().startswith("freebsd")) return "i486"; if (triple.getOSName().startswith("netbsd")) return "i486"; #if LDC_LLVM_VER >= 302 // All x86 devices running Android have core2 as their common // denominator. This makes a better choice than pentium4. if (triple.getEnvironment() == llvm::Triple::Android) return "core2"; #endif // Fallback to p4. return "pentium4"; }
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); getFilePaths().push_back( getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64")); }
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); getProgramPaths().push_back(getDriver().getInstalledDir()); getFilePaths().push_back(getDriver().SysRoot + "/lib"); }
SanitizerKind swift::parseSanitizerArgValues(const llvm::opt::Arg *A, const llvm::Triple &Triple, DiagnosticEngine &Diags) { SanitizerKind kind = SanitizerKind::None; // Find the sanitizer kind. SanitizerKind pKind = SanitizerKind::None; for (int i = 0, n = A->getNumValues(); i != n; ++i) { kind = llvm::StringSwitch<SanitizerKind>(A->getValue(i)) .Case("address", SanitizerKind::Address) .Case("thread", SanitizerKind::Thread) .Default(SanitizerKind::None); if (kind == SanitizerKind::None) { Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument, A->getOption().getPrefixedName(), A->getValue(i)); return kind; } // Currently, more than one sanitizer cannot be enabled at the same time. if (pKind != SanitizerKind::None && pKind != kind) { SmallString<128> pb; SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with, (A->getOption().getPrefixedName() + toStringRef(pKind)).toStringRef(pb), (A->getOption().getPrefixedName() + toStringRef(kind)).toStringRef(b)); } pKind = kind; } if (kind == SanitizerKind::None) return kind; // Check if the target is supported for this sanitizer. // None of the sanitizers work on Linux right now. if (!Triple.isOSDarwin()) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + toStringRef(kind)).toStringRef(b), Triple.getTriple()); } // Thread Sanitizer only works on OS X and the simulators. It's only supported // on 64 bit architectures. if (kind == SanitizerKind::Thread && (!(Triple.isMacOSX() || tripleIsAnySimulator(Triple)) || !Triple.isArch64Bit())) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + toStringRef(kind)).toStringRef(b), Triple.getTriple()); } return kind; }
CudaInstallationDetector::CudaInstallationDetector( const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args) : D(D) { struct Candidate { std::string Path; bool StrictChecking; Candidate(std::string Path, bool StrictChecking = false) : Path(Path), StrictChecking(StrictChecking) {} }; SmallVector<Candidate, 4> Candidates; // In decreasing order so we prefer newer versions to older versions. std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"}; if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) { Candidates.emplace_back( Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ).str()); } else if (HostTriple.isOSWindows()) { for (const char *Ver : Versions) Candidates.emplace_back( D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" + Ver); } else { if (!Args.hasArg(clang::driver::options::OPT_cuda_path_ignore_env)) { // Try to find ptxas binary. If the executable is located in a directory // called 'bin/', its parent directory might be a good guess for a valid // CUDA installation. // However, some distributions might installs 'ptxas' to /usr/bin. In that // case the candidate would be '/usr' which passes the following checks // because '/usr/include' exists as well. To avoid this case, we always // check for the directory potentially containing files for libdevice, // even if the user passes -nocudalib. if (llvm::ErrorOr<std::string> ptxas = llvm::sys::findProgramByName("ptxas")) { SmallString<256> ptxasAbsolutePath; llvm::sys::fs::real_path(*ptxas, ptxasAbsolutePath); StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath); if (llvm::sys::path::filename(ptxasDir) == "bin") Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir), /*StrictChecking=*/true); } } Candidates.emplace_back(D.SysRoot + "/usr/local/cuda"); for (const char *Ver : Versions) Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver); if (Distro(D.getVFS()).IsDebian()) // Special case for Debian to have nvidia-cuda-toolkit work // out of the box. More info on http://bugs.debian.org/882505 Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); } bool NoCudaLib = Args.hasArg(options::OPT_nocudalib); for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; if (InstallPath.empty() || !D.getVFS().exists(InstallPath)) continue; BinPath = InstallPath + "/bin"; IncludePath = InstallPath + "/include"; LibDevicePath = InstallPath + "/nvvm/libdevice"; auto &FS = D.getVFS(); if (!(FS.exists(IncludePath) && FS.exists(BinPath))) continue; bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking); if (CheckLibDevice && !FS.exists(LibDevicePath)) continue; // On Linux, we have both lib and lib64 directories, and we need to choose // based on our triple. On MacOS, we have only a lib directory. // // It's sufficient for our purposes to be flexible: If both lib and lib64 // exist, we choose whichever one matches our triple. Otherwise, if only // lib exists, we use it. if (HostTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64")) LibPath = InstallPath + "/lib64"; else if (FS.exists(InstallPath + "/lib")) LibPath = InstallPath + "/lib"; else continue; llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile = FS.getBufferForFile(InstallPath + "/version.txt"); if (!VersionFile) { // CUDA 7.0 doesn't have a version.txt, so guess that's our version if // version.txt isn't present. Version = CudaVersion::CUDA_70; } else { Version = ParseCudaVersionFile((*VersionFile)->getBuffer()); } if (Version >= CudaVersion::CUDA_90) { // CUDA-9+ uses single libdevice file for all GPU variants. std::string FilePath = LibDevicePath + "/libdevice.10.bc"; if (FS.exists(FilePath)) { for (const char *GpuArchName : {"sm_20", "sm_30", "sm_32", "sm_35", "sm_50", "sm_52", "sm_53", "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) { const CudaArch GpuArch = StringToCudaArch(GpuArchName); if (Version >= MinVersionForCudaArch(GpuArch) && Version <= MaxVersionForCudaArch(GpuArch)) LibDeviceMap[GpuArchName] = FilePath; } } } else { std::error_code EC; for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { StringRef FilePath = LI->path(); StringRef FileName = llvm::sys::path::filename(FilePath); // Process all bitcode filenames that look like // libdevice.compute_XX.YY.bc const StringRef LibDeviceName = "libdevice."; if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc"))) continue; StringRef GpuArch = FileName.slice( LibDeviceName.size(), FileName.find('.', LibDeviceName.size())); LibDeviceMap[GpuArch] = FilePath.str(); // Insert map entries for specifc devices with this compute // capability. NVCC's choice of the libdevice library version is // rather peculiar and depends on the CUDA version. if (GpuArch == "compute_20") { LibDeviceMap["sm_20"] = FilePath; LibDeviceMap["sm_21"] = FilePath; LibDeviceMap["sm_32"] = FilePath; } else if (GpuArch == "compute_30") { LibDeviceMap["sm_30"] = FilePath; if (Version < CudaVersion::CUDA_80) { LibDeviceMap["sm_50"] = FilePath; LibDeviceMap["sm_52"] = FilePath; LibDeviceMap["sm_53"] = FilePath; } LibDeviceMap["sm_60"] = FilePath; LibDeviceMap["sm_61"] = FilePath; LibDeviceMap["sm_62"] = FilePath; } else if (GpuArch == "compute_35") { LibDeviceMap["sm_35"] = FilePath; LibDeviceMap["sm_37"] = FilePath; } else if (GpuArch == "compute_50") { if (Version >= CudaVersion::CUDA_80) { LibDeviceMap["sm_50"] = FilePath; LibDeviceMap["sm_52"] = FilePath; LibDeviceMap["sm_53"] = FilePath; } } } } // Check that we have found at least one libdevice that we can link in if // -nocudalib hasn't been specified. if (LibDeviceMap.empty() && !NoCudaLib) continue; IsValid = true; break; } }
CudaInstallationDetector::CudaInstallationDetector( const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args) : D(D) { SmallVector<std::string, 4> CudaPathCandidates; // In decreasing order so we prefer newer versions to older versions. std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"}; if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) { CudaPathCandidates.push_back( Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ)); } else if (HostTriple.isOSWindows()) { for (const char *Ver : Versions) CudaPathCandidates.push_back( D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" + Ver); } else { CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda"); for (const char *Ver : Versions) CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver); } for (const auto &CudaPath : CudaPathCandidates) { if (CudaPath.empty() || !D.getVFS().exists(CudaPath)) continue; InstallPath = CudaPath; BinPath = CudaPath + "/bin"; IncludePath = InstallPath + "/include"; LibDevicePath = InstallPath + "/nvvm/libdevice"; auto &FS = D.getVFS(); if (!(FS.exists(IncludePath) && FS.exists(BinPath) && FS.exists(LibDevicePath))) continue; // On Linux, we have both lib and lib64 directories, and we need to choose // based on our triple. On MacOS, we have only a lib directory. // // It's sufficient for our purposes to be flexible: If both lib and lib64 // exist, we choose whichever one matches our triple. Otherwise, if only // lib exists, we use it. if (HostTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64")) LibPath = InstallPath + "/lib64"; else if (FS.exists(InstallPath + "/lib")) LibPath = InstallPath + "/lib"; else continue; llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile = FS.getBufferForFile(InstallPath + "/version.txt"); if (!VersionFile) { // CUDA 7.0 doesn't have a version.txt, so guess that's our version if // version.txt isn't present. Version = CudaVersion::CUDA_70; } else { Version = ParseCudaVersionFile((*VersionFile)->getBuffer()); } std::error_code EC; for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { StringRef FilePath = LI->path(); StringRef FileName = llvm::sys::path::filename(FilePath); // Process all bitcode filenames that look like libdevice.compute_XX.YY.bc const StringRef LibDeviceName = "libdevice."; if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc"))) continue; StringRef GpuArch = FileName.slice( LibDeviceName.size(), FileName.find('.', LibDeviceName.size())); LibDeviceMap[GpuArch] = FilePath.str(); // Insert map entries for specifc devices with this compute // capability. NVCC's choice of the libdevice library version is // rather peculiar and depends on the CUDA version. if (GpuArch == "compute_20") { LibDeviceMap["sm_20"] = FilePath; LibDeviceMap["sm_21"] = FilePath; LibDeviceMap["sm_32"] = FilePath; } else if (GpuArch == "compute_30") { LibDeviceMap["sm_30"] = FilePath; if (Version < CudaVersion::CUDA_80) { LibDeviceMap["sm_50"] = FilePath; LibDeviceMap["sm_52"] = FilePath; LibDeviceMap["sm_53"] = FilePath; } LibDeviceMap["sm_60"] = FilePath; LibDeviceMap["sm_61"] = FilePath; LibDeviceMap["sm_62"] = FilePath; } else if (GpuArch == "compute_35") { LibDeviceMap["sm_35"] = FilePath; LibDeviceMap["sm_37"] = FilePath; } else if (GpuArch == "compute_50") { if (Version >= CudaVersion::CUDA_80) { LibDeviceMap["sm_50"] = FilePath; LibDeviceMap["sm_52"] = FilePath; LibDeviceMap["sm_53"] = FilePath; } } } IsValid = true; break; } }
OptionSet<SanitizerKind> swift::parseSanitizerArgValues( const llvm::opt::ArgList &Args, const llvm::opt::Arg *A, const llvm::Triple &Triple, DiagnosticEngine &Diags, llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists) { OptionSet<SanitizerKind> sanitizerSet; // Find the sanitizer kind. for (int i = 0, n = A->getNumValues(); i != n; ++i) { auto kind = llvm::StringSwitch<Optional<SanitizerKind>>(A->getValue(i)) .Case("address", SanitizerKind::Address) .Case("thread", SanitizerKind::Thread) .Case("fuzzer", SanitizerKind::Fuzzer) .Default(None); bool isShared = kind && *kind != SanitizerKind::Fuzzer; if (!kind) { Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument, A->getOption().getPrefixedName(), A->getValue(i)); } else { // Support is determined by existance of the sanitizer library. bool sanitizerSupported = sanitizerRuntimeLibExists(toFileName(*kind), isShared); // TSan is explicitly not supported for 32 bits. if (*kind == SanitizerKind::Thread && !Triple.isArch64Bit()) sanitizerSupported = false; if (!sanitizerSupported) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + toStringRef(*kind)) .toStringRef(b), Triple.getTriple()); } else { sanitizerSet |= *kind; } } } // Check that we're one of the known supported targets for sanitizers. if (!(Triple.isOSDarwin() || Triple.isOSLinux() || Triple.isOSWindows())) { SmallString<128> b; Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target, (A->getOption().getPrefixedName() + StringRef(A->getAsString(Args))).toStringRef(b), Triple.getTriple()); } // Address and thread sanitizers can not be enabled concurrently. if ((sanitizerSet & SanitizerKind::Thread) && (sanitizerSet & SanitizerKind::Address)) { SmallString<128> b1; SmallString<128> b2; Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with, (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Address)).toStringRef(b1), (A->getOption().getPrefixedName() + toStringRef(SanitizerKind::Thread)).toStringRef(b2)); } return sanitizerSet; }
MipsLinkingContext::MipsLinkingContext(llvm::Triple triple) : ELFLinkingContext(triple, createTarget(triple, *this)), _flagsMerger(triple.isArch64Bit()) {}
static bool isTSanSupported( const llvm::Triple &Triple, llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) { return Triple.isArch64Bit() && sanitizerRuntimeLibExists("tsan"); }