diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index eab8206b104d..06c2647149df 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -360,4 +360,8 @@ def note_suggest_disabling_all_checkers : Note< def warn_poison_system_directories : Warning < "include location '%0' is unsafe for cross-compilation">, InGroup>, DefaultIgnore; + +def warn_opencl_unsupported_core_feature : Warning< + "%0 is a core feature in %select{OpenCL C|C++ for OpenCL}1 version %2 but not supported on this target">, + InGroup, DefaultIgnore; } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index b91cee9a9e5f..7d4e670c7e7d 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1286,3 +1286,5 @@ in addition with the pragmas or -fmax-tokens flag to get any warnings. def WebAssemblyExceptionSpec : DiagGroup<"wasm-exception-spec">; def RTTI : DiagGroup<"rtti">; + +def OpenCLCoreFeaturesDiagGroup : DiagGroup<"pedantic-core-features">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 8b3da909dd11..274ed728d94d 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1246,7 +1246,8 @@ def warn_pragma_unknown_extension : Warning< def warn_pragma_unsupported_extension : Warning< "unsupported OpenCL extension %0 - ignoring">, InGroup; def warn_pragma_extension_is_core : Warning< - "OpenCL extension %0 is core feature or supported optional core feature - ignoring">, InGroup>, DefaultIgnore; + "OpenCL extension %0 is core feature or supported optional core feature - ignoring">, + InGroup, DefaultIgnore; // OpenCL errors. def err_opencl_taking_function_address_parser : Error< diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h index 17923d2b8d3c..44fda029411f 100644 --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -59,6 +59,7 @@ static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO, OpenCLVersionID Code = encodeOpenCLVersion(CLVer); return Mask & Code; } + } // end anonymous namespace /// OpenCL supported extensions and optional core features @@ -167,6 +168,17 @@ public: using OpenCLOptionInfoMap = llvm::StringMap; + template + static bool isOpenCLOptionCoreIn(const LangOptions &LO, Args &&... args) { + return OpenCLOptionInfo(std::forward(args)...).isCoreIn(LO); + } + + template + static bool isOpenCLOptionAvailableIn(const LangOptions &LO, + Args &&... args) { + return OpenCLOptionInfo(std::forward(args)...).isAvailableIn(LO); + } + private: // Option is enabled via pragma bool isEnabled(llvm::StringRef Ext) const; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 77b474633359..3300fe012aa8 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1234,6 +1234,12 @@ public: return false; } + /// Check if target has a given feature enabled + virtual bool hasFeatureEnabled(const llvm::StringMap &Features, + StringRef Name) const { + return Features.lookup(Name); + } + /// Enable or disable a specific target feature; /// the feature name must be valid. virtual void setFeatureEnabled(llvm::StringMap &Features, @@ -1481,7 +1487,8 @@ public: virtual void setSupportedOpenCLOpts() {} virtual void supportAllOpenCLOpts(bool V = true) { -#define OPENCLEXTNAME(Ext) getTargetOpts().OpenCLFeaturesMap[#Ext] = V; +#define OPENCLEXTNAME(Ext) \ + setFeatureEnabled(getTargetOpts().OpenCLFeaturesMap, #Ext, V); #include "clang/Basic/OpenCLExtensions.def" } @@ -1501,10 +1508,6 @@ public: } } - /// Define OpenCL macros based on target settings and language version - void getOpenCLFeatureDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; - /// Get supported OpenCL extensions and optional core features. llvm::StringMap &getSupportedOpenCLOpts() { return getTargetOpts().OpenCLFeaturesMap; @@ -1544,6 +1547,11 @@ public: return true; } + /// Check that OpenCL target has valid options setting based on OpenCL + /// version. + virtual bool validateOpenCLTarget(const LangOptions &Opts, + DiagnosticsEngine &Diags) const; + virtual void setAuxTarget(const TargetInfo *Aux) {} /// Whether target allows debuginfo types for decl only variables/functions. diff --git a/clang/lib/Basic/OpenCLOptions.cpp b/clang/lib/Basic/OpenCLOptions.cpp index 78b7493855e6..7a647f02b1bd 100644 --- a/clang/lib/Basic/OpenCLOptions.cpp +++ b/clang/lib/Basic/OpenCLOptions.cpp @@ -85,9 +85,8 @@ void OpenCLOptions::support(llvm::StringRef Ext, bool V) { } OpenCLOptions::OpenCLOptions() { -#define OPENCL_GENERIC_EXTENSION(Ext, WithPragma, AvailVer, CoreVer, OptVer) \ - OptMap.insert_or_assign( \ - #Ext, OpenCLOptionInfo{WithPragma, AvailVer, CoreVer, OptVer}); +#define OPENCL_GENERIC_EXTENSION(Ext, ...) \ + OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__}); #include "clang/Basic/OpenCLExtensions.def" } diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 8df5cb7a3a61..894db333613e 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -726,30 +726,24 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return Target.release(); } +/// validateOpenCLTarget - Check that OpenCL target has valid +/// options setting based on OpenCL version. +bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts, + DiagnosticsEngine &Diags) const { + const llvm::StringMap &OpenCLFeaturesMap = getSupportedOpenCLOpts(); -/// getOpenCLFeatureDefines - Define OpenCL macros based on target settings -/// and language version -void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - // FIXME: OpenCL options which affect language semantics/syntax - // should be moved into LangOptions, thus macro definitions of - // such options is better to be done in clang::InitializePreprocessor. - auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer, - unsigned CoreVersions, - unsigned OptionalVersions) { - // Check if extension is supported by target and is available in this - // OpenCL version - auto It = getTargetOpts().OpenCLFeaturesMap.find(Name); - if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() && - OpenCLOptions::OpenCLOptionInfo(false, AvailVer, CoreVersions, - OptionalVersions) - .isAvailableIn(Opts)) - Builder.defineMacro(Name); + auto diagnoseNotSupportedCore = [&](llvm::StringRef Name, auto... OptArgs) { + if (OpenCLOptions::isOpenCLOptionCoreIn(Opts, OptArgs...) && + !hasFeatureEnabled(OpenCLFeaturesMap, Name)) + Diags.Report(diag::warn_opencl_unsupported_core_feature) + << Name << Opts.OpenCLCPlusPlus + << Opts.getOpenCLVersionTuple().getAsString(); }; -#define OPENCL_GENERIC_EXTENSION(Ext, WithPragma, Avail, Core, Opt) \ - defineOpenCLExtMacro(#Ext, Avail, Core, Opt); +#define OPENCL_GENERIC_EXTENSION(Ext, ...) \ + diagnoseNotSupportedCore(#Ext, __VA_ARGS__); #include "clang/Basic/OpenCLExtensions.def" - // Assume compiling for FULL profile - Builder.defineMacro("__opencl_c_int64"); + // For now assume that OpenCL target is always + // valid and just provide necessary diagnostics + return true; } diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 75d4aa77ab6e..ee5b6cb3c087 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -1398,13 +1398,13 @@ bool X86TargetInfo::validateOperandSize(const llvm::StringMap &FeatureMap, return Size <= 64; case 'z': // XMM0/YMM/ZMM0 - if (FeatureMap.lookup("avx512f")) + if (hasFeatureEnabled(FeatureMap, "avx512f")) // ZMM0 can be used if target supports AVX512F. return Size <= 512U; - else if (FeatureMap.lookup("avx")) + else if (hasFeatureEnabled(FeatureMap, "avx")) // YMM0 can be used if target supports AVX. return Size <= 256U; - else if (FeatureMap.lookup("sse")) + else if (hasFeatureEnabled(FeatureMap, "sse")) return Size <= 128U; return false; case 'i': @@ -1418,10 +1418,10 @@ bool X86TargetInfo::validateOperandSize(const llvm::StringMap &FeatureMap, break; case 'v': case 'x': - if (FeatureMap.lookup("avx512f")) + if (hasFeatureEnabled(FeatureMap, "avx512f")) // 512-bit zmm registers can be used if target supports AVX512F. return Size <= 512U; - else if (FeatureMap.lookup("avx")) + else if (hasFeatureEnabled(FeatureMap, "avx")) // 256-bit ymm registers can be used if target supports AVX. return Size <= 256U; return Size <= 128U; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index b76baae2e013..4a765b9203cc 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -133,6 +133,11 @@ bool CompilerInstance::createTarget() { // FIXME: can we disable FEnvAccess? } + // We should do it here because target knows nothing about + // language options when it's being created. + if (getLangOpts().OpenCL) + getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()); + // Inform the target of the language options. // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 557869a2571e..41b08ed56134 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -601,6 +601,29 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_coroutines", "201703L"); } +/// InitializeOpenCLFeatureTestMacros - Define OpenCL macros based on target +/// settings and language version +void InitializeOpenCLFeatureTestMacros(const TargetInfo &TI, + const LangOptions &Opts, + MacroBuilder &Builder) { + const llvm::StringMap &OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); + // FIXME: OpenCL options which affect language semantics/syntax + // should be moved into LangOptions. + auto defineOpenCLExtMacro = [&](llvm::StringRef Name, auto... OptArgs) { + // Check if extension is supported by target and is available in this + // OpenCL version + if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Name) && + OpenCLOptions::isOpenCLOptionAvailableIn(Opts, OptArgs...)) + Builder.defineMacro(Name); + }; +#define OPENCL_GENERIC_EXTENSION(Ext, ...) \ + defineOpenCLExtMacro(#Ext, __VA_ARGS__); +#include "clang/Basic/OpenCLExtensions.def" + + // Assume compiling for FULL profile + Builder.defineMacro("__opencl_c_int64"); +} + static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, @@ -1137,7 +1160,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // OpenCL definitions. if (LangOpts.OpenCL) { - TI.getOpenCLFeatureDefines(LangOpts, Builder); + InitializeOpenCLFeatureTestMacros(TI, LangOpts, Builder); if (TI.getTriple().isSPIR()) Builder.defineMacro("__IMAGE_SUPPORT__"); diff --git a/clang/test/Misc/nvptx.unsupported_core.cl b/clang/test/Misc/nvptx.unsupported_core.cl new file mode 100644 index 000000000000..b56a4828914e --- /dev/null +++ b/clang/test/Misc/nvptx.unsupported_core.cl @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -cl-std=CL2.0 -triple nvptx-unknown-unknown -Wpedantic-core-features %s 2> %t +// RUN: FileCheck --check-prefixes=CHECK-C < %t %s +// RUN: %clang_cc1 -cl-std=CLC++ -triple nvptx-unknown-unknown -Wpedantic-core-features %s 2> %t +// RUN: FileCheck --check-prefixes=CHECK-CPP < %t %s + +// CHECK-C: cl_khr_3d_image_writes is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK-CPP: cl_khr_3d_image_writes is a core feature in C++ for OpenCL version 1.0 but not supported on this target diff --git a/clang/test/Misc/r600.unsupported_core.cl b/clang/test/Misc/r600.unsupported_core.cl new file mode 100644 index 000000000000..db3d74880d8b --- /dev/null +++ b/clang/test/Misc/r600.unsupported_core.cl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -cl-std=CL2.0 -triple r600-unknown-unknown -Wpedantic-core-features %s 2> %t +// RUN: FileCheck < %t %s + +// CHECK: cl_khr_byte_addressable_store is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK: cl_khr_global_int32_base_atomics is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK: cl_khr_global_int32_extended_atomics is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK: cl_khr_local_int32_base_atomics is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK: cl_khr_local_int32_extended_atomics is a core feature in OpenCL C version 2.0 but not supported on this target +// CHECK: cl_khr_3d_image_writes is a core feature in OpenCL C version 2.0 but not supported on this target