OpenCL 1.0 support: attributes


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74280 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index a5b7ad4..7d3009b 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -72,6 +72,7 @@
     Packed,
     Pure,
     Regparm,
+    ReqdWorkGroupSize,   // OpenCL-specific
     Section,
     Sentinel,
     StdCall,
@@ -501,6 +502,27 @@
   static bool classof(const RegparmAttr *A) { return true; }
 };
 
+class ReqdWorkGroupSizeAttr : public Attr {
+  unsigned X, Y, Z;
+public:
+  ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
+  : Attr(ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
+
+  unsigned getXDim() const { return X; }
+  unsigned getYDim() const { return Y; }
+  unsigned getZDim() const { return Z; }
+
+  virtual Attr *clone(ASTContext &C) const { 
+    return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z); 
+  }
+  
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Attr *A) {
+    return A->getKind() == ReqdWorkGroupSize;
+  }
+  static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
+};
+  
 // Checker-specific attributes.
 DEF_SIMPLE_ATTR(CFReturnsRetained);
 DEF_SIMPLE_ATTR(NSReturnsRetained);
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index 26cebf0..50ca88a 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -97,6 +97,7 @@
     AT_warn_unused_result,
     AT_weak,
     AT_weak_import,
+    AT_reqd_wg_size,
     IgnoredAttribute,
     UnknownAttribute
   };
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 3dd84c7..3f6ae35 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -489,6 +489,14 @@
       New = ::new (*Context) NonNullAttr(ArgNums.data(), Size);
       break;
     }
+        
+    case Attr::ReqdWorkGroupSize: {
+      unsigned X = Record[Idx++];
+      unsigned Y = Record[Idx++];
+      unsigned Z = Record[Idx++];
+      New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
+      break;
+    }
 
     SIMPLE_ATTR(ObjCException);
     SIMPLE_ATTR(ObjCNSObject);
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e7bacab..808df70 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -1622,6 +1622,12 @@
     case Attr::Regparm:
       Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
       break;
+        
+    case Attr::ReqdWorkGroupSize:
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
+      Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
+      break;
 
     case Attr::Section:
       AddString(cast<SectionAttr>(Attr)->getName(), Record);
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 3fb6f95..5ee668a 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -118,6 +118,7 @@
   case 13:
     if (!memcmp(Str, "address_space", 13)) return AT_address_space;
     if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
+    if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute;
     break;
   case 14:
     if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
@@ -136,6 +137,8 @@
     if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
     if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
     break;            
+  case 20:
+    if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
   case 22:
     if (!memcmp(Str, "no_instrument_function", 22))
       return AT_no_instrument_function;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9a8e342..c11383c 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -149,13 +149,35 @@
             }
           }
         } else { // not an identifier
+          switch (Tok.getKind()) {
+          case tok::r_paren:
           // parse a possibly empty comma separated list of expressions
-          if (Tok.is(tok::r_paren)) { 
             // __attribute__(( nonnull() ))
             ConsumeParen(); // ignore the right paren loc for now
             CurrAttr = new AttributeList(AttrName, AttrNameLoc, 
                                          0, SourceLocation(), 0, 0, CurrAttr);
-          } else { 
+            break;
+          case tok::kw_char:
+          case tok::kw_wchar_t:
+          case tok::kw_bool:
+          case tok::kw_short:
+          case tok::kw_int:
+          case tok::kw_long:
+          case tok::kw_signed:
+          case tok::kw_unsigned:
+          case tok::kw_float:
+          case tok::kw_double:
+          case tok::kw_void:
+          case tok::kw_typeof:
+            // If it's a builtin type name, eat it and expect a rparen
+            // __attribute__(( vec_type_hint(char) ))
+            ConsumeToken();
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 
+                                         0, SourceLocation(), 0, 0, CurrAttr);
+            if (Tok.is(tok::r_paren))
+              ConsumeParen();
+            break;
+          default:
             // __attribute__(( aligned(16) ))
             ExprVector ArgExprs(Actions);
             bool ArgExprsOk = true;
@@ -181,6 +203,7 @@
                            SourceLocation(), ArgExprs.take(), ArgExprs.size(),
                            CurrAttr);
             }
+            break;
           }
         }
       } else {
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index d57630e..f7dd930 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -915,6 +915,30 @@
   D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
 }
 
+static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
+                                    Sema &S) {
+  // Attribute has 3 arguments.
+  if (Attr.getNumArgs() != 3) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  unsigned WGSize[3];
+  for (unsigned i = 0; i < 3; ++i) {
+    Expr *E = static_cast<Expr *>(Attr.getArg(i));
+    llvm::APSInt ArgNum(32);
+    if (!E->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "reqd_work_group_size" << E->getSourceRange();
+      return;
+    }
+    WGSize[i] = (unsigned) ArgNum.getZExtValue();
+  }
+  D->addAttr(S.Context, 
+             ::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
+                                                     WGSize[2]));
+}
+
 static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
   // Attribute has no arguments.
   if (Attr.getNumArgs() != 1) {
@@ -1736,6 +1760,9 @@
   case AttributeList::AT_cf_returns_retained:
     HandleNSReturnsRetainedAttr(D, Attr, S); break;
 
+  case AttributeList::AT_reqd_wg_size:
+    HandleReqdWorkGroupSize(D, Attr, S); break;
+
   case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
   case AttributeList::AT_section:     HandleSectionAttr   (D, Attr, S); break;
   case AttributeList::AT_stdcall:     HandleStdCallAttr   (D, Attr, S); break;