From: Steve Naroff Date: Wed, 18 Jul 2007 18:00:27 +0000 (+0000) Subject: First round of extended vector support. Here is an overview... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=73322924127c873c13101b705dd823f5539ffa5f;p=clang First round of extended vector support. Here is an overview... - 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 --- diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index e2447b972a..41905c8ecd 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -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(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(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) { diff --git a/Sema/Sema.h b/Sema/Sema.h index e386001214..f87cee60a9 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -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. diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index baa54649a2..c546df27cc 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -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(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(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(canonType)) - canonType = PT->getPointeeType().getTypePtr(); - else if (ArrayType *AT = dyn_cast(canonType)) - canonType = AT->getElementType().getTypePtr(); - else if (FunctionType *FT = dyn_cast(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(canonType)) + canonType = PT->getPointeeType().getTypePtr(); + else if (ArrayType *AT = dyn_cast(canonType)) + canonType = AT->getElementType().getTypePtr(); + else if (FunctionType *FT = dyn_cast(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); } diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index fc599b51f7..93f5a64310 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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()'. /// diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 437eb48581..7ec97cff49 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -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. /// diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 7486883b31..5459e35c89 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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,