azabaznov updated this revision to Diff 307436.
azabaznov marked 24 inline comments as done.
azabaznov added a comment.

Addressed almost all technical and cosmetic concerns concerns. Except putting 
reference of `OpenCLOptions` in `Sema` due to const of `TargetInfo`. I think 
I'll think about that later. Also:

1. Added new target hook to define extensions/features macros in one step 
(target settings + option)
2. Define generic address space macro if pipes or device enqueue is supported.
3. Did some minor refactoring of `OpenCLOptions.h` and `OpenCLExtensions.def`.




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89869/new/

https://reviews.llvm.org/D89869

Files:
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/include/clang/Basic/OpenCLOptions.h
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets.cpp
  clang/lib/Frontend/InitPreprocessor.cpp
  clang/lib/Headers/opencl-c-base.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/SemaOpenCL/opencl-feature-extension-simult.cl
  clang/test/SemaOpenCL/opencl-feature-generic-as-req.cl
  clang/test/SemaOpenCL/opencl-features.cl

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
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-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/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/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/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/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/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/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/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/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/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/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<Info> OptMap;
+
+  // e.g. __opencl_c_fp64 and cl_khr_fp64
+  llvm::StringMap<StringRef> 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<Info>::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<Info>::iterator I = OptMap.begin(),
          E = OptMap.end(); I != E; ++I)
       I->second.Enabled = false;
   }
 
-  void enableSupportedCore(LangOptions LO) {
+  void enableSupportedCore() {
     for (llvm::StringMap<Info>::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/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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to