diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -11,6 +11,7 @@ namespace llvm { class StringRef; +class Twine; class VersionTuple; } // namespace llvm @@ -30,7 +31,7 @@ }; const char *CudaVersionToString(CudaVersion V); // Input is "Major.Minor" -CudaVersion CudaStringToVersion(llvm::StringRef S); +CudaVersion CudaStringToVersion(const llvm::Twine &S); enum class CudaArch { UNKNOWN, diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -60,6 +60,9 @@ "but installation at %3 is %4. Use --cuda-path to specify a different CUDA " "install, pass a different GPU arch with --cuda-gpu-arch, or pass " "--no-cuda-version-check.">; +def warn_drv_unknown_cuda_version: Warning< + "Unknown CUDA version %0. Assuming the latest supported version %1">, + InGroup; def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">; def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">; def err_drv_invalid_thread_model_for_target : Error< diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1113,6 +1113,9 @@ // compiling CUDA C/C++ but which is not compatible with the CUDA spec. def CudaCompat : DiagGroup<"cuda-compat">; +// Warning about unknown CUDA SDK version. +def CudaUnknownVersion: DiagGroup<"unknown-cuda-version">; + // A warning group for warnings about features supported by HIP but // ignored by CUDA. def HIPOnly : DiagGroup<"hip-only">; diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -2,6 +2,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/VersionTuple.h" @@ -31,8 +32,8 @@ llvm_unreachable("invalid enum"); } -CudaVersion CudaStringToVersion(llvm::StringRef S) { - return llvm::StringSwitch(S) +CudaVersion CudaStringToVersion(const llvm::Twine &S) { + return llvm::StringSwitch(S.str()) .Case("7.0", CudaVersion::CUDA_70) .Case("7.5", CudaVersion::CUDA_75) .Case("8.0", CudaVersion::CUDA_80) @@ -40,7 +41,8 @@ .Case("9.1", CudaVersion::CUDA_91) .Case("9.2", CudaVersion::CUDA_92) .Case("10.0", CudaVersion::CUDA_100) - .Case("10.1", CudaVersion::CUDA_101); + .Case("10.1", CudaVersion::CUDA_101) + .Default(CudaVersion::UNKNOWN); } const char *CudaArchToString(CudaArch A) { diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -33,37 +33,24 @@ // Parses the contents of version.txt in an CUDA installation. It should // contain one line of the from e.g. "CUDA Version 7.5.2". -static CudaVersion ParseCudaVersionFile(llvm::StringRef V) { +static CudaVersion ParseCudaVersionFile(const Driver &D, llvm::StringRef V) { if (!V.startswith("CUDA Version ")) return CudaVersion::UNKNOWN; V = V.substr(strlen("CUDA Version ")); - int Major = -1, Minor = -1; - auto First = V.split('.'); - auto Second = First.second.split('.'); - if (First.first.getAsInteger(10, Major) || - Second.first.getAsInteger(10, Minor)) + SmallVector VersionParts; + V.split(VersionParts, '.'); + if (VersionParts.size() < 2) return CudaVersion::UNKNOWN; + Twine MajorMinor = VersionParts[0] + "." + VersionParts[1]; + CudaVersion Version = CudaStringToVersion(MajorMinor); + if (Version != CudaVersion::UNKNOWN) + return Version; - if (Major == 7 && Minor == 0) { - // This doesn't appear to ever happen -- version.txt doesn't exist in the - // CUDA 7 installs I've seen. But no harm in checking. - return CudaVersion::CUDA_70; - } - if (Major == 7 && Minor == 5) - return CudaVersion::CUDA_75; - if (Major == 8 && Minor == 0) - return CudaVersion::CUDA_80; - if (Major == 9 && Minor == 0) - return CudaVersion::CUDA_90; - if (Major == 9 && Minor == 1) - return CudaVersion::CUDA_91; - if (Major == 9 && Minor == 2) - return CudaVersion::CUDA_92; - if (Major == 10 && Minor == 0) - return CudaVersion::CUDA_100; - if (Major == 10 && Minor == 1) - return CudaVersion::CUDA_101; - return CudaVersion::UNKNOWN; + // Issue a warning and assume that the version we've found is compatible with + // the latest version we support. + D.Diag(diag::warn_drv_unknown_cuda_version) + << MajorMinor.str() << CudaVersionToString(CudaVersion::LATEST); + return CudaVersion::LATEST; } CudaInstallationDetector::CudaInstallationDetector( @@ -161,7 +148,7 @@ // version.txt isn't present. Version = CudaVersion::CUDA_70; } else { - Version = ParseCudaVersionFile((*VersionFile)->getBuffer()); + Version = ParseCudaVersionFile(D, (*VersionFile)->getBuffer()); } if (Version >= CudaVersion::CUDA_90) { diff --git a/clang/lib/Headers/__clang_cuda_runtime_wrapper.h b/clang/lib/Headers/__clang_cuda_runtime_wrapper.h --- a/clang/lib/Headers/__clang_cuda_runtime_wrapper.h +++ b/clang/lib/Headers/__clang_cuda_runtime_wrapper.h @@ -48,7 +48,7 @@ #include "cuda.h" #if !defined(CUDA_VERSION) #error "cuda.h did not define CUDA_VERSION" -#elif CUDA_VERSION < 7000 || CUDA_VERSION > 10010 +#elif CUDA_VERSION < 7000 #error "Unsupported CUDA version!" #endif diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/bin/.keep b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/bin/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/include/.keep b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/include/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/lib/.keep b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/lib/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/lib64/.keep b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/lib64/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/nvvm/libdevice/libdevice.10.bc b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/nvvm/libdevice/libdevice.10.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt new file mode 100644 --- /dev/null +++ b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt @@ -0,0 +1 @@ +CUDA Version 999.999.999 diff --git a/clang/test/Driver/cuda-version-check.cu b/clang/test/Driver/cuda-version-check.cu --- a/clang/test/Driver/cuda-version-check.cu +++ b/clang/test/Driver/cuda-version-check.cu @@ -8,6 +8,8 @@ // RUN: FileCheck %s --check-prefix=OK // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA-unknown/usr/local/cuda 2>&1 %s | \ +// RUN: FileCheck %s --check-prefix=UNKNOWN_VERSION // The installation at Inputs/CUDA is CUDA 7.0, which doesn't support sm_60. // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ @@ -58,3 +60,5 @@ // ERR_SM61: error: GPU arch sm_61 {{.*}} // ERR_SM61-NOT: error: GPU arch sm_61 + +// UNKNOWN_VERSION: Unknown CUDA version 999.999. Assuming the latest supported version