Index: include/clang/Basic/OpenCLOptions.h =================================================================== --- include/clang/Basic/OpenCLOptions.h +++ include/clang/Basic/OpenCLOptions.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H +#include "llvm/ADT/StringRef.h" + namespace clang { /// \brief OpenCL supported extensions and optional core features @@ -29,8 +31,33 @@ } // Enable all options. - void setAll() { -#define OPENCLEXT(nm) nm = 1; + void setAll(bool Enable = true) { +#define OPENCLEXT(nm) nm = Enable ? 1 : 0; +#include "clang/Basic/OpenCLExtensions.def" + } + + void set(llvm::StringRef Ext, bool Enable = true) { + assert(!Ext.empty() && "Extension is empty."); + + switch (Ext[0]) { + case '+': + Enable = true; + Ext = Ext.drop_front(); + break; + case '-': + Enable = false; + Ext = Ext.drop_front(); + break; + } + + if (Ext.equals("all")) { + setAll(Enable); + } + +#define OPENCLEXT(nm) \ + if (Ext.equals(#nm)) { \ + nm = Enable ? 1 : 0; \ + } #include "clang/Basic/OpenCLExtensions.def" } Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -981,6 +981,13 @@ /// \brief Set supported OpenCL extensions and optional core features. virtual void setSupportedOpenCLOpts() {} + /// \brief Set supported OpenCL extensions as written on command line + virtual void setOpenCLExtensionOpts() { + for (const auto &Ext:getTargetOpts().OpenCLExtensionsAsWritten) { + getTargetOpts().SupportedOpenCLOptions.set(Ext); + } + } + /// \brief Get supported OpenCL extensions and optional core features. OpenCLOptions &getSupportedOpenCLOpts() { return getTargetOpts().SupportedOpenCLOptions; Index: include/clang/Basic/TargetOptions.h =================================================================== --- include/clang/Basic/TargetOptions.h +++ include/clang/Basic/TargetOptions.h @@ -58,6 +58,10 @@ /// Supported OpenCL extensions and optional core features. OpenCLOptions SupportedOpenCLOptions; + + /// \brief The list of OpenCL extensions to enable or disable, as written on + /// the command line. + std::vector OpenCLExtensionsAsWritten; }; } // end namespace clang Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -391,6 +391,8 @@ HelpText<"OpenCL only. Allow denormals to be flushed to zero.">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group, Flags<[CC1Option]>, HelpText<"OpenCL only. Specify that single precision floating-point divide and sqrt used in the program source are correctly rounded.">; +def cl_ext_EQ : CommaJoined<["-"], "cl-ext=">, Group, Flags<[CC1Option]>, + HelpText<"OpenCL only. Enable or disable specific OpenCL extensions.">; def client__name : JoinedOrSeparate<["-"], "client_name">; def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -1874,6 +1874,8 @@ Opts.cl_khr_global_int32_extended_atomics = 1; Opts.cl_khr_local_int32_base_atomics = 1; Opts.cl_khr_local_int32_extended_atomics = 1; + + setOpenCLExtensionOpts(); } }; @@ -2157,6 +2159,7 @@ Opts.cl_amd_media_ops = 1; Opts.cl_amd_media_ops2 = 1; } + setOpenCLExtensionOpts(); } LangAS::ID getOpenCLImageAddrSpace() const override { @@ -2848,6 +2851,7 @@ void setSupportedOpenCLOpts() override { getSupportedOpenCLOpts().setAll(); + setOpenCLExtensionOpts(); } }; @@ -8007,6 +8011,7 @@ // Assume all OpenCL extensions and optional core features are supported // for SPIR since it is a generic target. getSupportedOpenCLOpts().setAll(); + setOpenCLExtensionOpts(); } }; Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2316,6 +2316,7 @@ // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); + Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ); } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Index: test/SemaOpenCL/extensions.cl =================================================================== --- test/SemaOpenCL/extensions.cl +++ test/SemaOpenCL/extensions.cl @@ -2,7 +2,20 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.1 // Test with a target not supporting fp64. -// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16 + +// Test with some extensions enabled or disabled by cmd-line args +// +// Target does not support fp64 and fp16 - override it +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+cl_khr_fp64,+cl_khr_fp16 +// +// Disable or enable all extensions +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -DNOFP64 -DNOFP16 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-cl_khr_fp64 -DNOFP64 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=-all,+cl_khr_fp64 -DNOFP16 + + void f1(double da) { // expected-error {{type 'double' requires cl_khr_fp64 extension}} double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} @@ -14,6 +27,11 @@ // expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}} #endif +#pragma OPENCL EXTENSION cl_khr_fp16 : enable +#ifdef NOFP16 +// expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp16' - ignoring}} +#endif + void f2(void) { double d; #ifdef NOFP64 @@ -34,3 +52,13 @@ void f3(void) { double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} } + +#ifdef CL_EXT_OPT +#pragma OPENCL EXTENSION cl_khr_fp64 : enable // expected-warning{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}} +#pragma OPENCL EXTENSION cl_khr_fp16 : enable + +#pragma OPENCL EXTENSION cl_khr_fp16 : disable +void f4(__global half* h) { + *h = 4.h; // expected-error{{half precision constant requires cl_khr_fp16}} +} +#endif