diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -44,6 +44,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/TrailingObjects.h" #include "llvm/Support/type_traits.h" @@ -1651,10 +1652,12 @@ /// target-specific vector type such as for AltiVec or Neon. unsigned VecKind : 3; - /// The number of elements in the vector. - unsigned NumElements : 29 - NumTypeBits; + unsigned ManyElements : 1; + /// Encoded number of elements in the vector. + /// If ManyElements is set, the count is 2 ** EncodedNumElements. + unsigned EncodedNumElements : 8; - enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 }; + enum { ManyElementsThreshold = 1 << 8 }; }; class AttributedTypeBitfields { @@ -3247,10 +3250,15 @@ public: QualType getElementType() const { return ElementType; } - unsigned getNumElements() const { return VectorTypeBits.NumElements; } + unsigned getNumElements() const { + return VectorTypeBits.ManyElements + ? (1 << VectorTypeBits.EncodedNumElements) + : VectorTypeBits.EncodedNumElements; + } - static bool isVectorSizeTooLarge(unsigned NumElements) { - return NumElements > VectorTypeBitfields::MaxNumElements; + static bool isVectorSizeValid(unsigned NumElements) { + return NumElements < VectorTypeBitfields::ManyElementsThreshold || + llvm::isPowerOf2_32(NumElements); } bool isSugared() const { return false; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2865,10 +2865,12 @@ "'callback' argument at position %0 references unavailable implicit 'this'">; def err_init_method_bad_return_type : Error< "init methods must return an object pointer type, not %0">; -def err_attribute_invalid_size : Error< +def err_attribute_noninteger_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; def err_attribute_size_too_large : Error<"vector size too large">; +def err_attribute_invalid_size : Error< + "vector size exceeds 256 and is not a power of two">; def err_typecheck_vector_not_convertable_implict_truncation : Error< "cannot convert between %select{scalar|vector}0 type %1 and vector type" " %2 as implicit conversion would cause truncation">; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -290,7 +290,15 @@ QualType canonType, VectorKind vecKind) : Type(tc, canonType, vecType->getDependence()), ElementType(vecType) { VectorTypeBits.VecKind = vecKind; - VectorTypeBits.NumElements = nElements; + if (nElements < VectorTypeBitfields::ManyElementsThreshold) { + VectorTypeBits.ManyElements = false; + VectorTypeBits.EncodedNumElements = nElements; + } else { + assert(llvm::isPowerOf2_32(nElements)); + VectorTypeBits.ManyElements = true; + VectorTypeBits.EncodedNumElements = llvm::Log2_32(nElements); + } + assert(getNumElements() == nElements); } /// getArrayElementTypeNoTypeQual - If this is an array type, return the diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -2436,7 +2437,12 @@ return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, VectorType::GenericVector); - unsigned VectorSize = static_cast(VecSize.getZExtValue() * 8); + if (!VecSize.isIntN(32)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << SizeExpr->getSourceRange(); + return QualType(); + } + unsigned VectorSize = VecSize.getZExtValue() * 8; unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); if (VectorSize == 0) { @@ -2446,13 +2452,13 @@ // vecSize is specified in bytes - convert to bits. if (VectorSize % TypeSize) { - Diag(AttrLoc, diag::err_attribute_invalid_size) + Diag(AttrLoc, diag::err_attribute_noninteger_size) << SizeExpr->getSourceRange(); return QualType(); } - if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) { - Diag(AttrLoc, diag::err_attribute_size_too_large) + if (!VectorType::isVectorSizeValid(VectorSize / TypeSize)) { + Diag(AttrLoc, diag::err_attribute_invalid_size) << SizeExpr->getSourceRange(); return QualType(); } @@ -2491,6 +2497,11 @@ // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. + if (!vecSize.isIntN(32)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << ArraySize->getSourceRange(); + return QualType(); + } unsigned vectorSize = static_cast(vecSize.getZExtValue()); if (vectorSize == 0) { @@ -2499,8 +2510,8 @@ return QualType(); } - if (VectorType::isVectorSizeTooLarge(vectorSize)) { - Diag(AttrLoc, diag::err_attribute_size_too_large) + if (!VectorType::isVectorSizeValid(vectorSize)) { + Diag(AttrLoc, diag::err_attribute_invalid_size) << ArraySize->getSourceRange(); return QualType(); } diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c --- a/clang/test/Sema/types.c +++ b/clang/test/Sema/types.c @@ -70,8 +70,18 @@ } // vector size too large -int __attribute__ ((vector_size(8192))) x1; // expected-error {{vector size too large}} -typedef int __attribute__ ((ext_vector_type(8192))) x2; // expected-error {{vector size too large}} +char __attribute__ ((vector_size(255))) v1; +char __attribute__ ((vector_size(256))) v2; +char __attribute__ ((vector_size(257))) v3; // expected-error {{vector size exceeds 256 and is not a power of two}} +char __attribute__ ((vector_size(512))) v4; +char __attribute__ ((vector_size(0x10000000))) v5; +char __attribute__ ((vector_size(0x100000000))) v6; // expected-error {{vector size too large}} +typedef int __attribute__ ((ext_vector_type(255))) e1; +typedef int __attribute__ ((ext_vector_type(256))) e2; +typedef int __attribute__ ((ext_vector_type(257))) e3; // expected-error {{vector size exceeds 256 and is not a power of two}} +typedef int __attribute__ ((ext_vector_type(512))) e4; +typedef int __attribute__ ((ext_vector_type(0x10000000))) e5; +typedef int __attribute__ ((ext_vector_type(0x100000000))) e6; // expected-error {{vector size too large}} // no support for vector enum type enum { e_2 } x3 __attribute__((vector_size(64))); // expected-error {{invalid vector element type}} diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -343,7 +343,7 @@ template struct PR15730 { typedef T __attribute__((vector_size(N * sizeof(T)))) type; - typedef T __attribute__((vector_size(8192))) type2; // #2 + typedef T __attribute__((vector_size(10000))) type2; // #2 typedef T __attribute__((vector_size(3))) type3; // #3 }; @@ -352,25 +352,27 @@ const TemplateVectorType::type Works2 = {}; // expected-error@#1 {{invalid vector element type 'bool'}} // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type NoBool; + const TemplateVectorType::type NoBool = {}; // expected-error@#1 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}} // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type NoComplex; + const TemplateVectorType::type NoComplex = {}; // expected-error@#1 {{vector size not an integral multiple of component size}} // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type BadSize; - // expected-error@#1 {{vector size too large}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type TooLarge; + const TemplateVectorType::type BadSize = {}; + const TemplateVectorType::type SmallNonPower = {}; + const TemplateVectorType::type LargePower = {}; + // expected-error@#1 {{vector size exceeds 256 and is not a power of two}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type LargeNonPower = {}; // expected-error@#1 {{zero vector size}} // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type Zero; + const TemplateVectorType::type Zero = {}; - // expected-error@#2 {{vector size too large}} + // expected-error@#2 {{not a power of two}} // expected-error@#3 {{vector size not an integral multiple of component size}} // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}} const PR15730<8, int>::type PR15730_1 = {}; - // expected-error@#2 {{vector size too large}} + // expected-error@#2 {{not a power of two}} // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}} const PR15730<8, char>::type2 PR15730_2 = {}; }