From 7bf779859a2c90017796c55d18b53ff00c27c9bf Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Mon, 11 Jan 2016 23:27:13 +0000 Subject: [PATCH] [CUDA] Reject values for --cuda-gpu-arch that are not of the form /sm_\d+/. Reviewers: tra Subscribers: cfe-commits, jhen, echristo Differential Revision: http://reviews.llvm.org/D16079 llvm-svn: 257413 --- .../clang/Basic/DiagnosticDriverKinds.td | 1 + clang/include/clang/Driver/Action.h | 7 +++- clang/lib/Driver/Action.cpp | 10 +++++- clang/lib/Driver/Driver.cpp | 8 +++-- clang/test/Driver/cuda-bad-arch.cu | 34 +++++++++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 clang/test/Driver/cuda-bad-arch.cu diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ce270bfffc69b..b04498f3188c0 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -22,6 +22,7 @@ def err_drv_unknown_stdin_type_clang_cl : Error< def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">; def err_drv_invalid_thread_model_for_target : Error< "invalid thread model '%0' in '%1' for this target">; def err_drv_invalid_linker_name : Error< diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index 3d10608f005de..88d0def44487a 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -15,6 +15,9 @@ #include "llvm/ADT/SmallVector.h" namespace llvm { + +class StringRef; + namespace opt { class Arg; } @@ -133,7 +136,7 @@ class BindArchAction : public Action { class CudaDeviceAction : public Action { virtual void anchor(); - /// GPU architecture to bind -- e.g 'sm_35'. + /// GPU architecture to bind. Always of the form /sm_\d+/. const char *GpuArchName; /// True when action results are not consumed by the host action (e.g when /// -fsyntax-only or --cuda-device-only options are used). @@ -145,6 +148,8 @@ class CudaDeviceAction : public Action { const char *getGpuArchName() const { return GpuArchName; } bool isAtTopLevel() const { return AtTopLevel; } + static bool IsValidGpuArchName(llvm::StringRef ArchName); + static bool classof(const Action *A) { return A->getKind() == CudaDeviceClass; } diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index bb76ae5ec0be3..0117f8ab0be1a 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -9,6 +9,7 @@ #include "clang/Driver/Action.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Regex.h" #include using namespace clang::driver; using namespace llvm::opt; @@ -54,7 +55,14 @@ void CudaDeviceAction::anchor() {} CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel) : Action(CudaDeviceClass, Input), GpuArchName(ArchName), - AtTopLevel(AtTopLevel) {} + AtTopLevel(AtTopLevel) { + assert(IsValidGpuArchName(GpuArchName)); +} + +bool CudaDeviceAction::IsValidGpuArchName(llvm::StringRef ArchName) { + static llvm::Regex RE("^sm_[0-9]+$"); + return RE.match(ArchName); +} void CudaHostAction::anchor() {} diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 8248a165c8172..1e0a48d529282 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1297,8 +1297,12 @@ static Action *buildCudaActions(Compilation &C, DerivedArgList &Args, if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) continue; A->claim(); - if (GpuArchNames.insert(A->getValue()).second) - GpuArchList.push_back(A->getValue()); + + const auto& Arch = A->getValue(); + if (!CudaDeviceAction::IsValidGpuArchName(Arch)) + C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << Arch; + else if (GpuArchNames.insert(Arch).second) + GpuArchList.push_back(Arch); } // Default to sm_20 which is the lowest common denominator for supported GPUs. diff --git a/clang/test/Driver/cuda-bad-arch.cu b/clang/test/Driver/cuda-bad-arch.cu new file mode 100644 index 0000000000000..67bac30060ce3 --- /dev/null +++ b/clang/test/Driver/cuda-bad-arch.cu @@ -0,0 +1,34 @@ +// Checks errors generated by passing a bad value for --cuda-gpu-arch. +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: nvptx-registered-target + +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=compute_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=foo_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_abc -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_20a -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_a20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=ssm_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_ -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s + +// BAD: error: Unsupported CUDA gpu architecture + +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_2 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_999 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s +// RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix OK %s + +// OK-NOT: error: Unsupported CUDA gpu architecture