Index: clang/include/clang/Basic/OpenCLExtensions.def =================================================================== --- clang/include/clang/Basic/OpenCLExtensions.def +++ clang/include/clang/Basic/OpenCLExtensions.def @@ -10,20 +10,27 @@ // //===----------------------------------------------------------------------===// -// Macro OPENCLEXT or OPENCLEXT_INTERNAL can be defined to enumerate the +// Macro OPENCLEXT or OPENCLCOREEXT_INTERNAL can be defined to enumerate the // OpenCL extensions listed in this file. // // If the extensions are to be enumerated without the supported OpenCL version, // define OPENCLEXT(ext) where ext is the name of the extension. // // If the extensions are to be enumerated with supported OpenCL version, -// define OPENCLEXT_INTERNAL(ext, avail, core) where +// define OPENCLCOREEXT_INTERNAL(ext, avail, core) where // ext - name of the extension or optional core feature. // avail - minimum OpenCL version supporting it. // core - minimum OpenCL version when the extension becomes optional core // feature or core feature. ~0U indicates not a core feature or an // optional core feature. // +// For OpenCL C 3.0 features, +// define OPENCLFEAT_INTERNAL(feat, avail, samext) +// feat - name of the feature. +// avail - minimum OpenCL version supporting it with no availability +// for compiler to disable it for OpenCL C less than 3.0. +// sameext - extension which is equivalent to a given feature +// // As per The OpenCL Extension Specification, Section 1.2, in this file, an // extension is defined if and only it either: // * affects the OpenCL language semantics or its syntax, @@ -34,65 +41,99 @@ // compilation flow is impacted, e.g. due to a difference of syntax or // semantics in the language compared to the core standard. -#ifndef OPENCLEXT_INTERNAL -#ifndef OPENCLEXT -#pragma error "macro OPENCLEXT or OPENCLEXT_INTERNAL is required" -#else -#define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext) -#endif // OPENCLEXT -#endif // OPENCLEXT_INTERNAL +#ifndef OPENCLCOREEXT_INTERNAL + #ifndef OPENCLEXT + #pragma error "macro OPENCLEXT or OPENCLCOREEXT_INTERNAL is required" + #else + #define OPENCLCOREEXT_INTERNAL(ext, ...) OPENCLEXT(ext) + #define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext) + #endif // OPENCLEXT +#else // OPENCLCOREEXT_INTERNAL + #define OPENCLEXT_INTERNAL(ext, avail) OPENCLCOREEXT_INTERNAL(ext, avail, ~0U) +#endif // OPENCLCOREEXT_INTERNAL + +#ifndef OPENCLFEAT_INTERNAL + #ifndef OPENCLEXT + #pragma error "macro OPENCLEXT or OPENCLFEAT_INTERNAL is required" + #else + #define OPENCLFEAT_INTERNAL(feat,...) OPENCLEXT(feat) + #endif // OPENCLEXT +#endif // OPENCLFEAT_INTERNAL + // OpenCL 1.0. -OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) -OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120) -OPENCLEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) -OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U) +OPENCLEXT_INTERNAL(cl_khr_fp16, 100) +OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100) +OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100) +OPENCLCOREEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) +OPENCLCOREEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_fp64, 100, 120) +OPENCLCOREEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) +OPENCLCOREEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) // EMBEDDED_PROFILE -OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) +OPENCLEXT_INTERNAL(cles_khr_int64, 110) // OpenCL 1.2. -OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U) +OPENCLEXT_INTERNAL(cl_khr_depth_images, 120) +OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120) // OpenCL 2.0. -OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_arithmetic, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle_relative, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_clustered_reduce, 200, ~0U) +OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200) +OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200) +OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroups, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_arithmetic, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle_relative, 200) +OPENCLEXT_INTERNAL(cl_khr_subgroup_clustered_reduce, 200) // Clang Extensions. -OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U) +OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100) // AMD OpenCL extensions -OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U) -OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U) +OPENCLEXT_INTERNAL(cl_amd_media_ops, 100) +OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100) // ARM OpenCL extensions -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120, ~0U) -OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120, ~0U) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120) +OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120) // Intel OpenCL extensions -OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U) -OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U) +OPENCLEXT_INTERNAL(cl_intel_subgroups, 120) +OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120) +OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120) + +// OpenCL C 3.0 features (6.2.1. Features) +OPENCLFEAT_INTERNAL(__opencl_c_pipes, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_generic_address_space, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_atomic_order_acq_rel, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_atomic_order_seq_cst, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_device_enqueue, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_read_write_images, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_program_scope_global_variables, 200, "") +OPENCLFEAT_INTERNAL(__opencl_c_fp64, 300, "cl_khr_fp64") +OPENCLFEAT_INTERNAL(__opencl_c_images, 100, "") + +// OpenCL C 3.0 only. Earlier versions should use extensions +// for following functionallity: +OPENCLFEAT_INTERNAL(__opencl_c_3d_image_writes, 300, "cl_khr_3d_image_writes") +OPENCLFEAT_INTERNAL(__opencl_c_fp64, 300, "cl_khr_fp64") + +// Note that __opencl_c_subgroups and cl_khr_subgroups are not equivalent +// as extension requires sub-group independent forward progress (4.2. Querying Devices) +OPENCLFEAT_INTERNAL(__opencl_c_subgroups, 300, "") #undef OPENCLEXT_INTERNAL +#undef OPENCLCOREEXT_INTERNAL +#undef OPENCLFEAT_INTERNAL #ifdef OPENCLEXT #undef OPENCLEXT Index: clang/include/clang/Basic/OpenCLOptions.h =================================================================== --- clang/include/clang/Basic/OpenCLOptions.h +++ clang/include/clang/Basic/OpenCLOptions.h @@ -22,16 +22,50 @@ /// OpenCL supported extensions and optional core features class OpenCLOptions { struct Info { - bool Supported; // Is this option supported - bool Enabled; // Is this option enabled - unsigned Avail; // Option starts to be available in this OpenCL version - unsigned Core; // Option becomes (optional) core feature in this OpenCL - // version - Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U) - :Supported(S), Enabled(E), Avail(A), Core(C){} + bool Supported = false; // Is this option supported + bool Enabled = false; // Is this option enabled + bool IsFeature = false; // Is this OpenCL feature + unsigned Avail = + 100; // Option starts to be available in this OpenCL version + unsigned Core = ~0U; // Option becomes (optional) core feature in this + // OpenCL version }; + + // OpenCL Version + unsigned CLVer = 120; + llvm::StringMap OptMap; + + // e.g. __opencl_c_fp64 and cl_khr_fp64 + llvm::StringMap EquivalentFeaturesExtensions; + + // For pre-OpenCL C 3.0 features are supported unconditionally + bool isSupportedFeatureForPreOCL30(llvm::StringRef Feat) const { + assert(CLVer < 300 && "Can't be called for OpenCL C 3.0 or higher"); + auto I = OptMap.find(Feat)->getValue(); + return I.IsFeature && I.Avail <= CLVer; + } + + void supportFeaturesForPreOCL30() { + assert(CLVer < 300 && "Can't be called for OpenCL C 3.0 or higher"); + for (auto &Opt : OptMap) + if (isSupportedFeatureForPreOCL30(Opt.getKey())) + OptMap[Opt.getKey()].Supported = true; + } + + // Simultaneously support feature and equivalent extension. + void supportSameExtensionsForSupportedFeatures() { + assert(CLVer >= 300 && "Can be called only for OpenCL C 3.0 or higher"); + for (auto &FeatExt : EquivalentFeaturesExtensions) + OptMap[FeatExt.getValue()].Supported = OptMap[FeatExt.getKey()].Supported; + } + public: + void setOpenCLVersion(const LangOptions &LO) { + // In C++ mode all extensions should work at least as in v2.0. + CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + } + bool isKnown(llvm::StringRef Ext) const { return OptMap.find(Ext) != OptMap.end(); } @@ -42,27 +76,21 @@ // Is supported as either an extension or an (optional) core feature for // OpenCL version \p CLVer. - bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const { - // In C++ mode all extensions should work at least as in v2.0. - auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + bool isSupported(llvm::StringRef Ext) const { auto I = OptMap.find(Ext)->getValue(); return I.Supported && I.Avail <= CLVer; } // Is supported (optional) OpenCL core features for OpenCL version \p CLVer. // For supported extension, return false. - bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const { - // In C++ mode all extensions should work at least as in v2.0. - auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + bool isSupportedCore(llvm::StringRef Ext) const { auto I = OptMap.find(Ext)->getValue(); return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core; } // Is supported OpenCL extension for OpenCL version \p CLVer. // For supported (optional) core feature, return false. - bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const { - // In C++ mode all extensions should work at least as in v2.0. - auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; + bool isSupportedExtension(llvm::StringRef Ext) const { auto I = OptMap.find(Ext)->getValue(); return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core); } @@ -77,7 +105,6 @@ /// \param V used when \p Ext is not prefixed by '+' or '-' void support(llvm::StringRef Ext, bool V = true) { assert(!Ext.empty() && "Extension is empty."); - switch (Ext[0]) { case '+': V = true; @@ -93,43 +120,74 @@ supportAll(V); return; } - OptMap[Ext].Supported = V; + + auto &Info = OptMap[Ext]; + + if (Info.IsFeature && (CLVer < 300) && V) { + if (isSupportedFeatureForPreOCL30(Ext)) + Info.Supported = true; + } else + Info.Supported = V; + } + + void addSupport(const OpenCLOptions &Opts) { + for (auto &I : Opts.OptMap) + if (I.second.Supported) + support(I.getKey(), true); } OpenCLOptions(){ -#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ - OptMap[#Ext].Avail = AvailVer; \ - OptMap[#Ext].Core = CoreVer; +#define OPENCLCOREEXT_INTERNAL(Ext, AvailVer, CoreVer) \ + OptMap[#Ext].Avail = AvailVer; \ + OptMap[#Ext].Core = CoreVer; +#define OPENCLFEAT_INTERNAL(Feat, AvailVer, SameExt) \ + OptMap[#Feat].Avail = AvailVer; \ + OptMap[#Feat].IsFeature = true; \ + if (llvm::StringRef(SameExt) != "") \ + EquivalentFeaturesExtensions[#Feat] = SameExt; #include "clang/Basic/OpenCLExtensions.def" } - void addSupport(const OpenCLOptions &Opts) { - for (auto &I:Opts.OptMap) - if (I.second.Supported) - OptMap[I.getKey()].Supported = true; + // Adjust existing OpenCL feature and extension support + void adjustFeatures() { + if (CLVer >= 300) { + supportSameExtensionsForSupportedFeatures(); + // OpenCL C compilers that define the feature macro __opencl_c_pipes or + // or __opencl_c_device_enqueue must also define the + // feature macro __opencl_c_generic_address_space. + if (OptMap["__opencl_c_pipes"].Supported || + OptMap["__opencl_c_device_enqueue"].Supported) + OptMap["__opencl_c_generic_address_space"].Supported = true; + // For OpenCL C 3.0 all other features are to be set by the + // targets or option explicitly. + return; + } + supportFeaturesForPreOCL30(); } void copy(const OpenCLOptions &Opts) { + CLVer = Opts.CLVer; OptMap = Opts.OptMap; + EquivalentFeaturesExtensions = Opts.EquivalentFeaturesExtensions; } // Turn on or off support of all options. void supportAll(bool On = true) { for (llvm::StringMap::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) - I->second.Supported = On; + support(I->getKey(), On); } - void disableAll() { + void disableAllExtensions() { for (llvm::StringMap::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) I->second.Enabled = false; } - void enableSupportedCore(LangOptions LO) { + void enableSupportedCore() { for (llvm::StringMap::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) - if (isSupportedCore(I->getKey(), LO)) + if (isSupportedCore(I->getKey())) I->second.Enabled = true; } Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1428,14 +1428,15 @@ /// Whether target defaults to the `power` alignment rules of AIX. virtual bool defaultsToAIXPowerAlignment() const { return false; } - /// Set supported OpenCL extensions and optional core features. - virtual void setSupportedOpenCLOpts() {} - - /// Set supported OpenCL extensions as written on command line - virtual void setOpenCLExtensionOpts() { - for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { - getTargetOpts().SupportedOpenCLOptions.support(Ext); - } + /// Set OpenCL features/extensions supported by target settings and option + void setOpenCLExtensions(const LangOptions &Opts) { + getTargetOpts().SupportedOpenCLOptions.setOpenCLVersion(Opts); + // Set options supported by the target + setSupportedOpenCLOpts(); + // Set option provided in option + setOpenCLExtensionOpts(); + // Adjust supported options + getTargetOpts().SupportedOpenCLOptions.adjustFeatures(); } /// Get supported OpenCL extensions and optional core features. @@ -1483,6 +1484,14 @@ virtual bool allowDebugInfoForExternalVar() const { return false; } protected: + /// Set supported OpenCL extensions and optional core features. + virtual void setSupportedOpenCLOpts() {} + /// Set supported OpenCL extensions as written on command line + virtual void setOpenCLExtensionOpts() { + for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { + getTargetOpts().SupportedOpenCLOptions.support(Ext); + } + } /// Copy type and layout related info. void copyAuxTarget(const TargetInfo *Aux); virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ clang/lib/Basic/TargetInfo.cpp @@ -356,6 +356,8 @@ } if (Opts.OpenCL) { + setOpenCLExtensions(Opts); + // OpenCL C requires specific widths for types, irrespective of // what these normally are for the target. // We also define long long and long double here, although the Index: clang/lib/Basic/Targets.cpp =================================================================== --- clang/lib/Basic/Targets.cpp +++ clang/lib/Basic/Targets.cpp @@ -694,8 +694,6 @@ if (!Target->handleTargetFeatures(Opts->Features, Diags)) return nullptr; - Target->setSupportedOpenCLOpts(); - Target->setOpenCLExtensionOpts(); Target->setMaxAtomicWidth(); if (!Target->validateTarget(Diags)) Index: clang/lib/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -1112,12 +1112,15 @@ // OpenCL definitions. if (LangOpts.OpenCL) { #define OPENCLEXT(Ext) \ - if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \ + if (TI.getSupportedOpenCLOpts().isSupported(#Ext)) \ Builder.defineMacro(#Ext); #include "clang/Basic/OpenCLExtensions.def" if (TI.getTriple().isSPIR()) Builder.defineMacro("__IMAGE_SUPPORT__"); + + // Assume compiling for FULL profile + Builder.defineMacro("__opencl_c_int64"); } if (TI.hasInt128Type() && LangOpts.CPlusPlus && LangOpts.GNUMode) { Index: clang/lib/Headers/opencl-c-base.h =================================================================== --- clang/lib/Headers/opencl-c-base.h +++ clang/lib/Headers/opencl-c-base.h @@ -9,6 +9,13 @@ #ifndef _OPENCL_BASE_H_ #define _OPENCL_BASE_H_ +// Define OpenCL header-only features for pre-OpenCL C 3.0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ == CL_VERSION_2_0) +#define __opencl_c_atomic_scope_device 1 +#define __opencl_c_atomic_scope_all_devices 1 +#define __opencl_c_work_group_collective_functions 1 +#endif + // built-in scalar data types: /** Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -772,13 +772,13 @@ // behavior is set to disable." if (Name == "all") { if (State == Disable) { - Opt.disableAll(); - Opt.enableSupportedCore(getLangOpts()); + Opt.disableAllExtensions(); + Opt.enableSupportedCore(); } else { PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; } } else if (State == Begin) { - if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) { + if (!Opt.isKnown(Name) || !Opt.isSupported(Name)) { Opt.support(Name); } Actions.setCurrentOpenCLExtension(Name); @@ -788,9 +788,9 @@ Actions.setCurrentOpenCLExtension(""); } else if (!Opt.isKnown(Name)) PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; - else if (Opt.isSupportedExtension(Name, getLangOpts())) + else if (Opt.isSupportedExtension(Name)) Opt.enable(Name, State == Enable); - else if (Opt.isSupportedCore(Name, getLangOpts())) + else if (Opt.isSupportedCore(Name)) PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; else PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -292,9 +292,10 @@ // Initialize predefined OpenCL types and supported extensions and (optional) // core features. if (getLangOpts().OpenCL) { + getOpenCLOptions().setOpenCLVersion(getLangOpts()); getOpenCLOptions().addSupport( Context.getTargetInfo().getSupportedOpenCLOpts()); - getOpenCLOptions().enableSupportedCore(getLangOpts()); + getOpenCLOptions().enableSupportedCore(); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) { Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -3587,6 +3587,7 @@ auto &Opt = OpenCLExtensions.OptMap[Name]; Opt.Supported = Record[I++] != 0; Opt.Enabled = Record[I++] != 0; + Opt.IsFeature = Record[I++] != 0; Opt.Avail = Record[I++]; Opt.Core = Record[I++]; } Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -3976,6 +3976,7 @@ auto V = I.getValue(); Record.push_back(V.Supported ? 1 : 0); Record.push_back(V.Enabled ? 1 : 0); + Record.push_back(V.IsFeature ? 1 : 0); Record.push_back(V.Avail); Record.push_back(V.Core); } Index: clang/test/SemaOpenCL/opencl-feature-extension-simult.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCL/opencl-feature-extension-simult.cl @@ -0,0 +1,23 @@ +// Testing with target which doesn't support 3d image writes and fp64 + +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=-all,__opencl_c_fp64 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_3d_image_writes +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_pipes +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_read_write_images +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_3d_image_writes,-cl_khr_3d_image_writes + +// expected-no-diagnostics + +#if (defined(cl_khr_fp64) && !defined(__opencl_c_fp64)) || \ + (defined(__opencl_c_fp64) && !defined(cl_khr_fp64)) + #error macros were not properly set up +#endif + +#if (defined(cl_khr_3d_image_writes) && \ + !defined(__opencl_c_3d_image_writes)) || \ + (defined(__opencl_c_3d_image_writes) && !defined(cl_khr_3d_image_writes)) + #error macros were not properly set up +#endif Index: clang/test/SemaOpenCL/opencl-feature-generic-as-req.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCL/opencl-feature-generic-as-req.cl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_pipes -DCHECK_PIPES +// RUN: %clang_cc1 %s -triple r600-unknown-unknown -E -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue -DCHECK_ENQUEU +// RUN: %clang_cc1 %s -triple spir64 -E -cl-std=CL3.0 -cl-ext=-all,+__opencl_c_pipes,-__opencl_c_generic_address_space -DCHECK_PIPES +// RUN: %clang_cc1 %s -triple spir64 -E -cl-std=CL3.0 -cl-ext=-all,+__opencl_c_device_enqueue,-__opencl_c_generic_address_space -DCHECK_ENQUEUE + +// expected-no-diagnostics + +#ifdef CHECK_PIPES + #if !defined(__opencl_c_pipes) + #error macros were not properly set + #endif +#endif + +#ifdef CHECK_ENQUEUE + #if !defined(__opencl_c_device_enqueue) + #error macros were not properly set + #endif +#endif + +#if defined(__opencl_c_pipes) || defined(__opencl_c_device_enqueue) + #if !defined(__opencl_c_generic_address_space) + #error macros were not properly set + #endif +#endif Index: clang/test/SemaOpenCL/opencl-features.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCL/opencl-features.cl @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CLC++ \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple r600-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple r600-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple r600-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CLC++ \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CLC++ \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CLC++ \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple spir-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple r600-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL2.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 +// RUN: %clang_cc1 -triple spir-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CLC++ \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL20 + +// x86_64 and spir support all features by default + +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL3.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL30 +// RUN: %clang_cc1 -triple r600-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL3.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL30 +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL3.0 \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL30 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL3.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL30 +// RUN: %clang_cc1 -triple spir-unknown-unknown -finclude-default-header %s -E -dM -o - -x cl -cl-std=CL3.0 -cl-ext=-all \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CL30 + +// CL20: #define __opencl_c_atomic_order_acq_rel 1 +// CL20: #define __opencl_c_atomic_order_seq_cst 1 +// CL20: #define __opencl_c_atomic_scope_all_devices 1 +// CL20: #define __opencl_c_atomic_scope_device 1 +// CL20: #define __opencl_c_device_enqueue 1 +// CL20: #define __opencl_c_generic_address_space 1 +// CL20: #define __opencl_c_images 1 +// CL20: #define __opencl_c_int64 1 +// CL20: #define __opencl_c_pipes 1 +// CL20: #define __opencl_c_program_scope_global_variables 1 +// CL20: #define __opencl_c_read_write_images 1 +// CL20: #define __opencl_c_work_group_collective_functions 1 +// CL20-NOT: __opencl_c_fp64 +// CL20-NOT: __opencl_c_3d_image_writes +// CL20-NOT: __opencl_c_subgroups + +// CL30: #define __opencl_c_int64 1 +// CL30-NOT: __opencl_c_atomic_order_acq_rel +// CL30-NOT: __opencl_c_atomic_order_seq_cst +// CL30-NOT: __opencl_c_atomic_scope_all_devices +// CL30-NOT: __opencl_c_atomic_scope_device +// CL30-NOT: __opencl_c_device_enqueue +// CL30-NOT: __opencl_c_generic_address_space +// CL30-NOT: __opencl_c_images +// CL30-NOT: __opencl_c_pipes +// CL30-NOT: __opencl_c_program_scope_global_variables +// CL30-NOT: __opencl_c_read_write_images +// CL30-NOT: __opencl_c_work_group_collective_functions +// CL30-NOT: __opencl_c_fp64 +// CL30-NOT: __opencl_c_3d_image_writes +// CL30-NOT: __opencl_c_subgroups