]> granicus.if.org Git - clang/commitdiff
First round of extended vector support. Here is an overview...
authorSteve Naroff <snaroff@apple.com>
Wed, 18 Jul 2007 18:00:27 +0000 (18:00 +0000)
committerSteve Naroff <snaroff@apple.com>
Wed, 18 Jul 2007 18:00:27 +0000 (18:00 +0000)
- added ocu_vector_type attribute, Sema::HandleOCUVectorTypeAttribute().
- added new AST node, OCUVectorType, a subclass of VectorType.
- added ASTContext::getOCUVectorType.
- changed ASTContext::convertToVectorType() to ASTContext::getVectorType(). This is
unrelated to extended vectors, however I was in the vicinity and it was on my todo list.
Added a FIXME to Sema::HandleVectorTypeAttribute to deal with converting complex types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40007 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/ASTContext.h
include/clang/AST/Type.h
include/clang/Basic/DiagnosticKinds.def

index e2447b972a93623150f74e719c4e27256d1dfea2..41905c8ecd1fc7fc9b55e03bf31f24c530e237a7 100644 (file)
@@ -392,19 +392,17 @@ QualType ASTContext::getArrayType(QualType EltTy,ArrayType::ArraySizeModifier AS
   return QualType(New, 0);
 }
 
-/// convertToVectorType - Return the unique reference to a vector type of
-/// the specified element type and size. VectorType can be a pointer, array,
-/// function, or built-in type (i.e. _Bool, integer, or float).
-QualType ASTContext::convertToVectorType(QualType vecType, unsigned NumElts) {
+/// getVectorType - Return the unique reference to a vector type of
+/// the specified element type and size. VectorType must be a built-in type.
+QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {
   BuiltinType *baseType;
   
   baseType = dyn_cast<BuiltinType>(vecType.getCanonicalType().getTypePtr());
-  assert(baseType != 0 && 
-         "convertToVectorType(): Complex vector types unimplemented");
+  assert(baseType != 0 && "getVectorType(): Expecting a built-in type");
          
   // Check if we've already instantiated a vector of this type.
   llvm::FoldingSetNodeID ID;
-  VectorType::Profile(ID, vecType, NumElts);      
+  VectorType::Profile(ID, vecType, NumElts, Type::Vector);      
   void *InsertPos = 0;
   if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(VTP, 0);
@@ -413,7 +411,7 @@ QualType ASTContext::convertToVectorType(QualType vecType, unsigned NumElts) {
   // so fill in the canonical type field.
   QualType Canonical;
   if (!vecType->isCanonical()) {
-    Canonical = convertToVectorType(vecType.getCanonicalType(), NumElts);
+    Canonical = getVectorType(vecType.getCanonicalType(), NumElts);
     
     // Get the new insert position for the node we care about.
     VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -425,6 +423,37 @@ QualType ASTContext::convertToVectorType(QualType vecType, unsigned NumElts) {
   return QualType(New, 0);
 }
 
+/// getOCUVectorType - Return the unique reference to an OCU vector type of
+/// the specified element type and size. VectorType must be a built-in type.
+QualType ASTContext::getOCUVectorType(QualType vecType, unsigned NumElts) {
+  BuiltinType *baseType;
+  
+  baseType = dyn_cast<BuiltinType>(vecType.getCanonicalType().getTypePtr());
+  assert(baseType != 0 && "getOCUVectorType(): Expecting a built-in type");
+         
+  // Check if we've already instantiated a vector of this type.
+  llvm::FoldingSetNodeID ID;
+  VectorType::Profile(ID, vecType, NumElts, Type::OCUVector);      
+  void *InsertPos = 0;
+  if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(VTP, 0);
+
+  // If the element type isn't canonical, this won't be a canonical type either,
+  // so fill in the canonical type field.
+  QualType Canonical;
+  if (!vecType->isCanonical()) {
+    Canonical = getOCUVectorType(vecType.getCanonicalType(), NumElts);
+    
+    // Get the new insert position for the node we care about.
+    VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(NewIP == 0 && "Shouldn't be in the map!");
+  }
+  OCUVectorType *New = new OCUVectorType(vecType, NumElts, Canonical);
+  VectorTypes.InsertNode(New, InsertPos);
+  Types.push_back(New);
+  return QualType(New, 0);
+}
+
 /// getFunctionTypeNoProto - Return a K&R style C function type like 'int()'.
 ///
 QualType ASTContext::getFunctionTypeNoProto(QualType ResultTy) {
index e386001214d3cb6894e8f04904ca902ddb5b78cb..f87cee60a98c581b9a55ca126fd49be81c52b9ed 100644 (file)
@@ -153,6 +153,7 @@ private:
   // for the variable, measured in bytes. If curType and rawAttr are well
   // formed, this routine will return a new vector type.
   QualType HandleVectorTypeAttribute(QualType curType, AttributeList *rawAttr);
+  QualType HandleOCUVectorTypeAttribute(QualType curType, AttributeList *rawAttr);
   
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
index baa54649a202a46a5f1c7953346fbe03e922ebf6..c546df27cc8cf661f610e9c1b2e062f3c7e2c693 100644 (file)
@@ -956,6 +956,17 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
         tDecl->setUnderlyingType(newType);
     }
   }
+  if (strcmp(rawAttr->getAttributeName()->getName(), "ocu_vector_type") == 0) {
+    if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
+      QualType newType = HandleOCUVectorTypeAttribute(tDecl->getUnderlyingType(), 
+                                                      rawAttr);
+      if (!newType.isNull()) // install the new vector type into the decl
+        tDecl->setUnderlyingType(newType);
+    } else {
+      Diag(rawAttr->getAttributeLoc(), 
+           diag::err_typecheck_ocu_vector_not_typedef);
+    }
+  }
   // FIXME: add other attributes...
 }
 
@@ -971,6 +982,42 @@ void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
   }
 }
 
+QualType Sema::HandleOCUVectorTypeAttribute(QualType curType, 
+                                            AttributeList *rawAttr) {
+  // check the attribute arugments.
+  if (rawAttr->getNumArgs() != 1) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments,
+         std::string("1"));
+    return QualType();
+  }
+  Expr *sizeExpr = static_cast<Expr *>(rawAttr->getArg(0));
+  llvm::APSInt vecSize(32);
+  if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_vector_size_not_int,
+         sizeExpr->getSourceRange());
+    return QualType();
+  }
+  // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+  // in conjunction with complex types (pointers, arrays, functions, etc.).
+  Type *canonType = curType.getCanonicalType().getTypePtr();
+  if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_invalid_vector_type,
+         curType.getCanonicalType().getAsString());
+    return QualType();
+  }
+  // unlike gcc's vector_size attribute, the size is specified as the 
+  // number of elements, not the number of bytes.
+  unsigned vectorSize = vecSize.getZExtValue(); 
+  
+  if (vectorSize == 0) {
+    Diag(rawAttr->getAttributeLoc(), diag::err_attribute_zero_size,
+         sizeExpr->getSourceRange());
+    return QualType();
+  }
+  // Instantiate the vector type, the number of elements is > 0.
+  return Context.getOCUVectorType(curType, vectorSize);
+}
+
 QualType Sema::HandleVectorTypeAttribute(QualType curType, 
                                          AttributeList *rawAttr) {
   // check the attribute arugments.
@@ -990,14 +1037,20 @@ QualType Sema::HandleVectorTypeAttribute(QualType curType,
   // vector arrays, and functions returning vectors.
   Type *canonType = curType.getCanonicalType().getTypePtr();
   
-  while (canonType->isPointerType() || canonType->isArrayType() ||
-         canonType->isFunctionType()) {
-    if (PointerType *PT = dyn_cast<PointerType>(canonType))
-      canonType = PT->getPointeeType().getTypePtr();
-    else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
-      canonType = AT->getElementType().getTypePtr();
-    else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
-      canonType = FT->getResultType().getTypePtr();
+  if (canonType->isPointerType() || canonType->isArrayType() ||
+      canonType->isFunctionType()) {
+    assert(1 && "HandleVector(): Complex type construction unimplemented");
+    /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
+        do {
+          if (PointerType *PT = dyn_cast<PointerType>(canonType))
+            canonType = PT->getPointeeType().getTypePtr();
+          else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
+            canonType = AT->getElementType().getTypePtr();
+          else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
+            canonType = FT->getResultType().getTypePtr();
+        } while (canonType->isPointerType() || canonType->isArrayType() ||
+                 canonType->isFunctionType());
+    */
   }
   // the base type must be integer or float.
   if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
@@ -1023,6 +1076,6 @@ QualType Sema::HandleVectorTypeAttribute(QualType curType,
   // Since OpenCU requires 3 element vectors (OpenCU 5.1.2), we don't restrict
   // the number of elements to be a power of two (unlike GCC).
   // Instantiate the vector type, the number of elements is > 0.
-  return Context.convertToVectorType(curType, vectorSize/typeSize);
+  return Context.getVectorType(curType, vectorSize/typeSize);
 }
 
index fc599b51f7f581cf0c3ff6353b8c9e2e659f2dd9..93f5a64310c124e24f664c7a3890cc43a1a1a5b1 100644 (file)
@@ -79,10 +79,13 @@ public:
   QualType getArrayType(QualType EltTy, ArrayType::ArraySizeModifier ASM,
                         unsigned EltTypeQuals, Expr *NumElts);
                         
-  /// convertToVectorType - Return the unique reference to a vector type of
-  /// the specified element type and size. VectorType can be a pointer, array,
-  /// function, or built-in type (i.e. _Bool, integer, or float).
-  QualType convertToVectorType(QualType VectorType, unsigned NumElts);
+  /// getVectorType - Return the unique reference to a vector type of
+  /// the specified element type and size. VectorType must be a built-in type.
+  QualType getVectorType(QualType VectorType, unsigned NumElts);
+
+  /// getOCUVectorType - Return the unique reference to an OCU vector type of
+  /// the specified element type and size. VectorType must be a built-in type.
+  QualType getOCUVectorType(QualType VectorType, unsigned NumElts);
 
   /// getFunctionTypeNoProto - Return a K&R style C function type like 'int()'.
   ///
index 437eb48581cdc753f1c2a03f79accc320af74e42..7ec97cff491d5b4f3088045e2858f7b9146e271f 100644 (file)
@@ -182,7 +182,7 @@ namespace clang {
 class Type {
 public:
   enum TypeClass {
-    Builtin, Complex, Pointer, Reference, Array, Vector,
+    Builtin, Complex, Pointer, Reference, Array, Vector, OCUVector,
     FunctionNoProto, FunctionProto,
     TypeName, Tagged
   };
@@ -450,17 +450,23 @@ public:
   static bool classof(const ArrayType *) { return true; }
 };
 
-/// VectorType - 
-///
+/// VectorType - GCC generic vector type. This type is created using
+/// __attribute__((vector_size(n)), where "n" specifies the vector size in 
+/// bytes. Since the constructor takes the number of vector elements, the 
+/// client is responsible for converting the size into the number of elements.
 class VectorType : public Type, public llvm::FoldingSetNode {
+protected:
   /// ElementType - The element type of the vector.
   QualType ElementType;
   
   /// NumElements - The number of elements in the vector.
   unsigned NumElements;
   
-  VectorType(QualType vecType, unsigned vectorSize, QualType canonType) :
-    Type(Vector, canonType), ElementType(vecType), NumElements(vectorSize) {} 
+  VectorType(QualType vecType, unsigned nElements, QualType canonType) :
+    Type(Vector, canonType), ElementType(vecType), NumElements(nElements) {} 
+  VectorType(TypeClass tc, QualType vecType, unsigned nElements, 
+    QualType canonType) : Type(tc, canonType), ElementType(vecType), 
+    NumElements(nElements) {} 
   friend class ASTContext;  // ASTContext creates these.
 public:
     
@@ -470,17 +476,35 @@ public:
   virtual void getAsStringInternal(std::string &InnerString) const;
   
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getElementType(), getNumElements());
+    Profile(ID, getElementType(), getNumElements(), getTypeClass());
   }
-  static void Profile(llvm::FoldingSetNodeID &ID,
-                      QualType ElementType, unsigned NumElements) {
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, 
+                      unsigned NumElements, TypeClass TypeClass) {
     ID.AddPointer(ElementType.getAsOpaquePtr());
     ID.AddInteger(NumElements);
+    ID.AddInteger(TypeClass);
+  }
+  static bool classof(const Type *T) { 
+    return T->getTypeClass() == Vector || T->getTypeClass() == OCUVector; 
   }
-  static bool classof(const Type *T) { return T->getTypeClass() == Vector; }
   static bool classof(const VectorType *) { return true; }
 };
 
+/// OCUVectorType - Extended vector type. This type is created using
+/// __attribute__((ocu_vector_type(n)), where "n" is the number of elements.
+/// Unlike vector_size, ocu_vector_type is only allowed on typedef's.
+/// This class will enable syntactic extensions, like C++ style initializers.
+class OCUVectorType : public VectorType {
+  OCUVectorType(QualType vecType, unsigned nElements, QualType canonType) :
+    VectorType(OCUVector, vecType, nElements, canonType) {} 
+  friend class ASTContext;  // ASTContext creates these.
+public:
+  static bool classof(const VectorType *T) { 
+    return T->getTypeClass() == OCUVector; 
+  }
+  static bool classof(const OCUVectorType *) { return true; }
+};
+
 /// FunctionType - C99 6.7.5.3 - Function Declarators.  This is the common base
 /// class of FunctionTypeNoProto and FunctionTypeProto.
 ///
index 7486883b3159162fbe7a086207066f811d383e1b..5459e35c89b10d09c7361d24e13cde5581c9462b 100644 (file)
@@ -441,6 +441,8 @@ DIAG(err_attribute_zero_size, ERROR,
      "zero vector size")
 DIAG(err_typecheck_vector_not_convertable, ERROR,
      "can't convert between vector values of different size ('%0' and '%1')")
+DIAG(err_typecheck_ocu_vector_not_typedef, ERROR,
+     "ocu_vector_type only applies to types, not variables")
 
 // Function Parameter Semantic Analysis.
 DIAG(err_void_param_with_identifier, ERROR,