yaxunl created this revision.
yaxunl added a reviewer: Anastasia.
yaxunl added subscribers: cfe-commits, bader, pxli168, tstellarAMD.

Allow user to use pragma to add supported extensions:

  #pragma OPENCL EXTENSION the_new_extension_name : register

After that, users can use

  #pragma OPENCL EXTENSION the_new_extension_name : enable/disable

in subsequent code. 


http://reviews.llvm.org/D21698

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Basic/OpenCLOptions.h
  include/clang/Serialization/ASTReader.h
  lib/Basic/Targets.cpp
  lib/Frontend/InitPreprocessor.cpp
  lib/Parse/ParsePragma.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaCast.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaType.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp
  test/PCH/opencl-extensions.cl
  test/Parser/opencl-pragma.cl
  test/SemaOpenCL/extension-register.cl

Index: test/SemaOpenCL/extension-register.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/extension-register.cl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : register // expected-warning {{register supported OpenCL extension or optional core feature - ignoring}}
+
+#pragma OPENCL EXTENSION all : register /* expected-warning {{expected 'disable' - ignoring}} */
+
+#pragma OPENCL EXTENSION my_ext : enable // expected-warning {{unknown OpenCL extension 'my_ext' - ignoring}}
+#pragma OPENCL EXTENSION my_ext : disable // expected-warning {{unknown OpenCL extension 'my_ext' - ignoring}}
+#pragma OPENCL EXTENSION my_ext : register
+#pragma OPENCL EXTENSION my_ext : register // expected-warning {{register supported OpenCL extension or optional core feature - ignoring}}
+#pragma OPENCL EXTENSION my_ext : enable
+#pragma OPENCL EXTENSION my_ext : disable 
+
Index: test/Parser/opencl-pragma.cl
===================================================================
--- test/Parser/opencl-pragma.cl
+++ test/Parser/opencl-pragma.cl
@@ -5,9 +5,13 @@
 #pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{unknown OpenCL extension 'cl_no_such_extension' - ignoring}} */
 
 #pragma OPENCL EXTENSION all : disable
-#pragma OPENCL EXTENSION all : enable /* expected-warning {{unknown OpenCL extension 'all' - ignoring}} */
+#pragma OPENCL EXTENSION all : enable /* expected-warning {{expected 'disable' - ignoring}} */
+#pragma OPENCL EXTENSION all : register /* expected-warning {{expected 'disable' - ignoring}} */
+#pragma OPENCL EXTENSION all : on /* expected-warning {{expected 'disable' - ignoring}} */
 
-#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable' or 'disable' - ignoring}} */
+#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable' or 'disable' or 'register' - ignoring}} */
+
+#pragma OPENCL EXTENSION my_ext : on /* expected-warning {{expected 'enable' or 'disable' or 'register' - ignoring}} */
 
 #pragma OPENCL FP_CONTRACT ON
 #pragma OPENCL FP_CONTRACT OFF
Index: test/PCH/opencl-extensions.cl
===================================================================
--- test/PCH/opencl-extensions.cl
+++ test/PCH/opencl-extensions.cl
@@ -6,10 +6,13 @@
 // Header.
 
 #pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#pragma OPENCL EXTENSION my_ext_example : register
 
 #else
 // Using the header.
 
+#pragma OPENCL EXTENSION my_extension : enable
+
 void test(void) {
   double d;
 }
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -3829,8 +3829,14 @@
 
   const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
   RecordData Record;
-#define OPENCLEXT(nm)  Record.push_back(Opts.nm);
-#include "clang/Basic/OpenCLExtensions.def"
+  for (const auto &I:Opts.OptMap) {
+    AddString(I.getKey(), Record);
+    auto V = I.getValue();
+    Record.push_back(V.Supported);
+    Record.push_back(V.Enabled);
+    Record.push_back(V.Avail);
+    Record.push_back(V.Core);
+  }
   Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
 }
 
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3097,8 +3097,14 @@
       break;
 
     case OPENCL_EXTENSIONS:
-      // Later tables overwrite earlier ones.
-      OpenCLExtensions.swap(Record);
+      for (unsigned I = 0, E = Record.size(); I != E; ) {
+        auto Name = ReadString(Record, I);
+        OpenCLExtensions.OptMap[Name] = {
+          static_cast<bool>(Record[I++]),
+          static_cast<bool>(Record[I++]),
+          static_cast<unsigned>(Record[I++]),
+          static_cast<unsigned>(Record[I++])};
+      }
       break;
 
     case TENTATIVE_DEFINITIONS:
@@ -6924,14 +6930,7 @@
     SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
   }
 
-  // FIXME: What happens if these are changed by a module import?
-  if (!OpenCLExtensions.empty()) {
-    unsigned I = 0;
-#define OPENCLEXT(nm)  SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
-#include "clang/Basic/OpenCLExtensions.def"
-
-    assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
-  }
+  SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
 
   UpdateSema();
 }
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1414,7 +1414,7 @@
 
     if (S.getLangOpts().OpenCL &&
         !((S.getLangOpts().OpenCLVersion >= 120) ||
-          S.getOpenCLOptions().cl_khr_fp64)) {
+          S.getOpenCLOptions().isEnabled("cl_khr_fp64"))) {
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
           << Result << "cl_khr_fp64";
       declarator.setInvalidType(true);
@@ -1478,24 +1478,25 @@
                 .Cases("atomic_int", "atomic_uint", "atomic_float",
                        "atomic_flag", true)
                 .Default(false);
-        if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
+        if (!S.getOpenCLOptions().isEnabled("cl_khr_int64_base_atomics") &&
+            !NoExtTypes) {
           S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
               << Result << "cl_khr_int64_base_atomics";
           declarator.setInvalidType(true);
         }
-        if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
-            !NoExtTypes) {
+        if (!S.getOpenCLOptions().isEnabled("cl_khr_int64_extended_atomics")
+            && !NoExtTypes) {
           S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
               << Result << "cl_khr_int64_extended_atomics";
           declarator.setInvalidType(true);
         }
-        if (!S.getOpenCLOptions().cl_khr_fp64 &&
+        if (!S.getOpenCLOptions().isEnabled("cl_khr_fp64") &&
             !TypeName.compare("atomic_double")) {
           S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
               << Result << "cl_khr_fp64";
           declarator.setInvalidType(true);
         }
-      } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
+      } else if (!S.getOpenCLOptions().isEnabled("cl_khr_gl_msaa_sharing") &&
                  (Result->isOCLImage2dArrayMSAADepthROType() ||
                   Result->isOCLImage2dArrayMSAADepthWOType() ||
                   Result->isOCLImage2dArrayMSAADepthRWType() ||
@@ -4008,7 +4009,7 @@
       // FIXME: This really should be in BuildFunctionType.
       if (T->isHalfType()) {
         if (S.getLangOpts().OpenCL) {
-          if (!S.getOpenCLOptions().cl_khr_fp16) {
+          if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
             S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
                 << T << 0 /*pointer hint*/;
             D.setInvalidType(true);
@@ -4214,7 +4215,7 @@
             // Disallow half FP parameters.
             // FIXME: This really should be in BuildFunctionType.
             if (S.getLangOpts().OpenCL) {
-              if (!S.getOpenCLOptions().cl_khr_fp16) {
+              if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
                 S.Diag(Param->getLocation(),
                   diag::err_opencl_half_param) << ParamTy;
                 D.setInvalidType();
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -665,7 +665,7 @@
     return E;
 
   // OpenCL usually rejects direct accesses to values of 'half' type.
-  if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+  if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
       T->isHalfType()) {
     Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
       << 0 << T;
@@ -3366,7 +3366,7 @@
   if (Literal.isFloatingLiteral()) {
     QualType Ty;
     if (Literal.isHalf){
-      if (getOpenCLOptions().cl_khr_fp16)
+      if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
         Ty = Context.HalfTy;
       else {
         Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -3388,7 +3388,7 @@
         Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
       } else if (getLangOpts().OpenCL &&
                  !((getLangOpts().OpenCLVersion >= 120) ||
-                   getOpenCLOptions().cl_khr_fp64)) {
+                   getOpenCLOptions().isEnabled("cl_khr_fp64"))) {
         Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
         Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
       }
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5861,7 +5861,7 @@
       NR = NR->getPointeeType();
     }
 
-    if (!getOpenCLOptions().cl_khr_fp16) {
+    if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
       // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
       // half array type (unless the cl_khr_fp16 extension is enabled).
       if (Context.getBaseElementType(R)->isHalfType()) {
@@ -6741,7 +6741,7 @@
   // OpenCL v1.2 s6.8 - The static qualifier is valid only in program
   // scope.
   if (getLangOpts().OpenCLVersion == 120 &&
-      !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+      !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
       NewVD->isStaticLocal()) {
     Diag(NewVD->getLocation(), diag::err_static_function_scope);
     NewVD->setInvalidDecl();
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp
+++ lib/Sema/SemaCast.cpp
@@ -2519,7 +2519,8 @@
     }
   }
 
-  if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
+  if (Self.getLangOpts().OpenCL &&
+      !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
     if (DestType->isHalfType()) {
       Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
         << DestType << SrcExpr.get()->getSourceRange();
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -209,14 +209,11 @@
     addImplicitTypedef("size_t", Context.getSizeType());
   }
 
-  // Initialize predefined OpenCL types and supported optional core features.
+  // Initialize predefined OpenCL types and supported extensions and (optional)
+  // core features.
   if (getLangOpts().OpenCL) {
-#define OPENCLEXT(Ext) \
-     if (Context.getTargetInfo().getSupportedOpenCLOpts().is_##Ext##_supported_core( \
-         getLangOpts().OpenCLVersion)) \
-       getOpenCLOptions().Ext = 1;
-#include "clang/Basic/OpenCLExtensions.def"
-
+    getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts());
+    getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion);
     addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
     addImplicitTypedef("event_t", Context.OCLEventTy);
     if (getLangOpts().OpenCLVersion >= 200) {
Index: lib/Sema/DeclSpec.cpp
===================================================================
--- lib/Sema/DeclSpec.cpp
+++ lib/Sema/DeclSpec.cpp
@@ -511,7 +511,7 @@
   // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
   // specifiers are not supported."
   if (S.getLangOpts().OpenCL &&
-      !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+      !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
     switch (SC) {
     case SCS_extern:
     case SCS_private_extern:
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -455,42 +455,44 @@
 }
 
 namespace {
-  typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
+  enum OpenCLExtState : char {
+    Disable, Enable, Register
+  };
+  typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
 }
 
 void Parser::HandlePragmaOpenCLExtension() {
   assert(Tok.is(tok::annot_pragma_opencl_extension));
-  OpenCLExtData data =
-      OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
-  unsigned state = data.getInt();
-  IdentifierInfo *ename = data.getPointer();
+  OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
+  auto State = Data->second;
+  auto Ident = Data->first;
   SourceLocation NameLoc = Tok.getLocation();
   ConsumeToken(); // The annotation token.
 
-  OpenCLOptions &f = Actions.getOpenCLOptions();
-  auto CLVer = getLangOpts().OpenCLVersion;
-  auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
+  auto &Opt = Actions.getOpenCLOptions();
+  auto Name = Ident->getName();
   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
   // overriding all previously issued extension directives, but only if the
   // behavior is set to disable."
-  if (state == 0 && ename->isStr("all")) {
-#define OPENCLEXT(nm) \
-    if (Supp.is_##nm##_supported_extension(CLVer)) \
-      f.nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
-  }
-#define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
-   if (Supp.is_##nm##_supported_extension(CLVer)) \
-     f.nm = state; \
-   else if (Supp.is_##nm##_supported_core(CLVer)) \
-     PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
-   else \
-     PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
-#include "clang/Basic/OpenCLExtensions.def"
-  else {
-    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
-    return;
-  }
+  if (Name == "all") {
+    if (State == Disable)
+      Opt.disableAll();
+    else
+      PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
+  } else if (State == Register) {
+    if (!Opt.isKnown(Name) ||
+        !Opt.isSupported(Name, getLangOpts().OpenCLVersion))
+      Opt.support(Name);
+    else
+      PP.Diag(NameLoc, diag::warn_pragma_register_supported);
+  } else if (!Opt.isKnown(Name))
+    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
+  else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
+    Opt.enable(Name, State == Enable);
+  else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
+    PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
+  else
+    PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
 }
 
 void Parser::HandlePragmaMSPointersToMembers() {
@@ -1410,29 +1412,32 @@
       "OPENCL";
     return;
   }
-  IdentifierInfo *ename = Tok.getIdentifierInfo();
+  IdentifierInfo *Ext = Tok.getIdentifierInfo();
   SourceLocation NameLoc = Tok.getLocation();
 
   PP.Lex(Tok);
   if (Tok.isNot(tok::colon)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
     return;
   }
 
   PP.Lex(Tok);
-  if (Tok.isNot(tok::identifier)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_register)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
     return;
   }
-  IdentifierInfo *op = Tok.getIdentifierInfo();
+  IdentifierInfo *Pred = Tok.getIdentifierInfo();
 
-  unsigned state;
-  if (op->isStr("enable")) {
-    state = 1;
-  } else if (op->isStr("disable")) {
-    state = 0;
-  } else {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+  OpenCLExtState State;
+  if (Pred->isStr("enable")) {
+    State = Enable;
+  } else if (Pred->isStr("disable")) {
+    State = Disable;
+  } else if (Pred->isStr("register"))
+    State = Register;
+  else {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
+      << Ext->isStr("all");
     return;
   }
   SourceLocation StateLoc = Tok.getLocation();
@@ -1444,19 +1449,21 @@
     return;
   }
 
-  OpenCLExtData data(ename, state);
+  auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
+  Info->first = Ext;
+  Info->second = State;
   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
                               1);
   Toks[0].startToken();
   Toks[0].setKind(tok::annot_pragma_opencl_extension);
   Toks[0].setLocation(NameLoc);
-  Toks[0].setAnnotationValue(data.getOpaqueValue());
+  Toks[0].setAnnotationValue(static_cast<void*>(Info));
   Toks[0].setAnnotationEndLoc(StateLoc);
   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
 
   if (PP.getPPCallbacks())
-    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 
-                                               StateLoc, state);
+    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext, 
+                                               StateLoc, State);
 }
 
 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
Index: lib/Frontend/InitPreprocessor.cpp
===================================================================
--- lib/Frontend/InitPreprocessor.cpp
+++ lib/Frontend/InitPreprocessor.cpp
@@ -958,7 +958,7 @@
   // OpenCL definitions.
   if (LangOpts.OpenCL) {
 #define OPENCLEXT(Ext) \
-    if (TI.getSupportedOpenCLOpts().is_##Ext##_supported( \
+    if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \
         LangOpts.OpenCLVersion)) \
       Builder.defineMacro(#Ext);
 #include "clang/Basic/OpenCLExtensions.def"
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -1864,16 +1864,16 @@
   }
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.cl_clang_storage_class_specifiers = 1;
-    Opts.cl_khr_gl_sharing = 1;
-    Opts.cl_khr_icd = 1;
+    Opts.support("cl_clang_storage_class_specifiers");
+    Opts.support("cl_khr_gl_sharing");
+    Opts.support("cl_khr_icd");
 
-    Opts.cl_khr_fp64 = 1;
-    Opts.cl_khr_byte_addressable_store = 1;
-    Opts.cl_khr_global_int32_base_atomics = 1;
-    Opts.cl_khr_global_int32_extended_atomics = 1;
-    Opts.cl_khr_local_int32_base_atomics = 1;
-    Opts.cl_khr_local_int32_extended_atomics = 1;
+    Opts.support("cl_khr_fp64");
+    Opts.support("cl_khr_byte_addressable_store");
+    Opts.support("cl_khr_global_int32_base_atomics");
+    Opts.support("cl_khr_global_int32_extended_atomics");
+    Opts.support("cl_khr_local_int32_base_atomics");
+    Opts.support("cl_khr_local_int32_extended_atomics");
   }
 };
 
@@ -2111,23 +2111,23 @@
 
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.cl_clang_storage_class_specifiers = 1;
-    Opts.cl_khr_icd = 1;
+    Opts.support("cl_clang_storage_class_specifiers");
+    Opts.support("cl_khr_icd");
 
     if (hasFP64)
-      Opts.cl_khr_fp64 = 1;
+      Opts.support("cl_khr_fp64");
     if (GPU >= GK_EVERGREEN) {
-      Opts.cl_khr_byte_addressable_store = 1;
-      Opts.cl_khr_global_int32_base_atomics = 1;
-      Opts.cl_khr_global_int32_extended_atomics = 1;
-      Opts.cl_khr_local_int32_base_atomics = 1;
-      Opts.cl_khr_local_int32_extended_atomics = 1;
+      Opts.support("cl_khr_byte_addressable_store");
+      Opts.support("cl_khr_global_int32_base_atomics");
+      Opts.support("cl_khr_global_int32_extended_atomics");
+      Opts.support("cl_khr_local_int32_base_atomics");
+      Opts.support("cl_khr_local_int32_extended_atomics");
     }
     if (GPU >= GK_SOUTHERN_ISLANDS) {
-      Opts.cl_khr_fp16 = 1;
-      Opts.cl_khr_int64_base_atomics = 1;
-      Opts.cl_khr_int64_extended_atomics = 1;
-      Opts.cl_khr_3d_image_writes = 1;
+      Opts.support("cl_khr_fp16");
+      Opts.support("cl_khr_int64_base_atomics");
+      Opts.support("cl_khr_int64_extended_atomics");
+      Opts.support("cl_khr_3d_image_writes");
     }
   }
 };
@@ -2805,7 +2805,7 @@
   }
 
   void setSupportedOpenCLOpts() override {
-    getSupportedOpenCLOpts().setAll();
+    getSupportedOpenCLOpts().supportAll();
   }
 };
 
@@ -7927,7 +7927,7 @@
   void setSupportedOpenCLOpts() override {
     // Assume all OpenCL extensions and optional core features are supported
     // for SPIR since it is a generic target.
-    getSupportedOpenCLOpts().setAll();
+    getSupportedOpenCLOpts().supportAll();
   }
 };
 
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -788,7 +788,7 @@
   SourceLocation PointersToMembersPragmaLocation;
 
   /// \brief The OpenCL extension settings.
-  SmallVector<uint64_t, 1> OpenCLExtensions;
+  OpenCLOptions OpenCLExtensions;
 
   /// \brief A list of the namespaces we've seen.
   SmallVector<uint64_t, 4> KnownNamespaces;
Index: include/clang/Basic/OpenCLOptions.h
===================================================================
--- include/clang/Basic/OpenCLOptions.h
+++ include/clang/Basic/OpenCLOptions.h
@@ -17,50 +17,100 @@
 
 #include <string>
 #include <vector>
+#include "llvm/ADT/StringMap.h"
 
 namespace clang {
 
 /// \brief 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;  // Options 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){}
+  };
+  llvm::StringMap<Info> OptMap;
 public:
-#define OPENCLEXT(nm) unsigned nm : 1;
-#include "clang/Basic/OpenCLExtensions.def"
+  bool isKnown(StringRef Ext) const {
+    return OptMap.find(Ext) != OptMap.end();
+  }
 
-  OpenCLOptions() {
-#define OPENCLEXT(nm)   nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
+  bool isEnabled(StringRef Ext) const {
+    return OptMap.find(Ext)->second.Enabled;
   }
 
-  // Enable all options.
-  void setAll() {
-#define OPENCLEXT(nm)   nm = 1;
-#include "clang/Basic/OpenCLExtensions.def"
+  // Is supported OpenCL extension or (optional) core feature for OpenCL version
+  // \p CLVer.
+  bool isSupported(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer;
   }
 
-  // Is supported with OpenCL version \p OCLVer.
-#define OPENCLEXT_INTERNAL(Ext, Avail, ...) \
-  bool is_##Ext##_supported(unsigned OCLVer) const { \
-    return Ext && OCLVer >= Avail; \
+  // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
+  // For supported extension, return false.
+  bool isSupportedCore(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer &&
+      I.Core != ~0U && CLVer >= I.Core;
   }
-#include "clang/Basic/OpenCLExtensions.def"
 
+  // Is supported OpenCL extension for OpenCL version \p CLVer.
+  // For supported (optional) core feature, return false.
+ bool isSupportedExtension(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer &&
+      (I.Core == ~0U || CLVer < I.Core);
+  }
 
-  // Is supported OpenCL extension with OpenCL version \p OCLVer.
-  // For supported optional core feature, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
-  bool is_##Ext##_supported_extension(unsigned CLVer) const { \
-    return is_##Ext##_supported(CLVer) && (Core == ~0U || CLVer < Core); \
+  void enable(StringRef Ext, bool V = true) {
+    OptMap[Ext].Enabled = V;
   }
-#include "clang/Basic/OpenCLExtensions.def"
 
-  // Is supported OpenCL core features with OpenCL version \p OCLVer.
-  // For supported extension, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
-  bool is_##Ext##_supported_core(unsigned CLVer) const { \
-    return is_##Ext##_supported(CLVer) && Core != ~0U && CLVer >= Core; \
+  void support(StringRef Ext, bool V = true) {
+    OptMap[Ext].Supported = V;
   }
+
+  OpenCLOptions(){
+#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
+    OptMap[#Ext].Avail = AvailVer; \
+    OptMap[#Ext].Core = CoreVer;
 #include "clang/Basic/OpenCLExtensions.def"
+  }
+
+  void addSupport(const OpenCLOptions &Opts) {
+    for (auto &I:Opts.OptMap)
+      if (I.second.Supported)
+        OptMap[I.getKey()].Supported = true;
+  }
+
+  void copy(const OpenCLOptions &Opts) {
+    OptMap = Opts.OptMap;
+  }
+
+  void supportAll() {
+    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+         E = OptMap.end(); I != E; ++I)
+      I->second.Supported = true;
+  }
+
+  void disableAll() {
+    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+         E = OptMap.end(); I != E; ++I)
+      I->second.Enabled = false;
+  }
+
+  void enableSupportedCore(unsigned CLVer) {
+    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+         E = OptMap.end(); I != E; ++I)
+      if (isSupportedCore(I->getKey(), CLVer))
+        I->second.Enabled = true;
+  }
 
+  friend class ASTWriter;
+  friend class ASTReader;
 };
 
 }  // end namespace clang
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -922,8 +922,10 @@
 // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
 def warn_pragma_expected_colon : Warning<
   "missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
-def warn_pragma_expected_enable_disable : Warning<
-  "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_predicate : Warning<
+  "expected %select{'enable' or 'disable' or 'register'|'disable'}0 - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_register_supported : Warning<
+  "register supported OpenCL extension or optional core feature - ignoring">, InGroup<IgnoredPragmas>;
 def warn_pragma_unknown_extension : Warning<
   "unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
 def warn_pragma_unsupported_extension : Warning<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to