improve altivec vector bool/pixel support, patch by Anton Yartsev
with several tweaks by me.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 80bda84..0be1778 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1514,7 +1514,7 @@
 /// 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,
-                                   bool IsAltiVec, bool IsPixel) {
+    VectorType::AltiVecSpecific AltiVecSpec) {
   BuiltinType *baseType;
 
   baseType = dyn_cast<BuiltinType>(getCanonicalType(vecType).getTypePtr());
@@ -1522,8 +1522,8 @@
 
   // Check if we've already instantiated a vector of this type.
   llvm::FoldingSetNodeID ID;
-  VectorType::Profile(ID, vecType, NumElts, Type::Vector,
-    IsAltiVec, IsPixel);
+  VectorType::Profile(ID, vecType, NumElts, Type::Vector, AltiVecSpec);
+
   void *InsertPos = 0;
   if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(VTP, 0);
@@ -1531,16 +1531,19 @@
   // 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() || IsAltiVec || IsPixel) {
-    Canonical = getVectorType(getCanonicalType(vecType),
-      NumElts, false, false);
+  if (!vecType.isCanonical() || (AltiVecSpec == VectorType::AltiVec)) {
+    // pass VectorType::NotAltiVec for AltiVecSpec to make AltiVec canonical
+    // vector type (except 'vector bool ...' and 'vector Pixel') the same as
+    // the equivalent GCC vector types
+    Canonical = getVectorType(getCanonicalType(vecType), NumElts,
+      VectorType::NotAltiVec);
 
     // 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!"); NewIP = NewIP;
   }
   VectorType *New = new (*this, TypeAlignment)
-    VectorType(vecType, NumElts, Canonical, IsAltiVec, IsPixel);
+    VectorType(vecType, NumElts, Canonical, AltiVecSpec);
   VectorTypes.InsertNode(New, InsertPos);
   Types.push_back(New);
   return QualType(New, 0);
@@ -1556,7 +1559,8 @@
 
   // Check if we've already instantiated a vector of this type.
   llvm::FoldingSetNodeID ID;
-  VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, false, false);
+  VectorType::Profile(ID, vecType, NumElts, Type::ExtVector,
+                      VectorType::NotAltiVec);
   void *InsertPos = 0;
   if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(VTP, 0);
@@ -4933,7 +4937,7 @@
   // Turn <4 x signed int> -> <4 x unsigned int>
   if (const VectorType *VTy = T->getAs<VectorType>())
     return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
-             VTy->getNumElements(), VTy->isAltiVec(), VTy->isPixel());
+             VTy->getNumElements(), VTy->getAltiVecSpecific());
 
   // For enums, we return the unsigned version of the base type.
   if (const EnumType *ETy = T->getAs<EnumType>())
@@ -5091,7 +5095,8 @@
 
     QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
     // FIXME: Don't know what to do about AltiVec.
-    Type = Context.getVectorType(ElementType, NumElements, false, false);
+    Type = Context.getVectorType(ElementType, NumElements,
+                                 VectorType::NotAltiVec);
     break;
   }
   case 'X': {
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index e1c2abd..8d347d1 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -440,9 +440,7 @@
       return false;
     if (Vec1->getNumElements() != Vec2->getNumElements())
       return false;
-    if (Vec1->isAltiVec() != Vec2->isAltiVec())
-      return false;
-    if (Vec1->isPixel() != Vec2->isPixel())
+    if (Vec1->getAltiVecSpecific() != Vec2->getAltiVecSpecific())
       return false;
     break;
   }
@@ -1191,8 +1189,7 @@
   
   return Importer.getToContext().getVectorType(ToElementType, 
                                                T->getNumElements(),
-                                               T->isAltiVec(),
-                                               T->isPixel());
+                                               T->getAltiVecSpecific());
 }
 
 QualType ASTNodeImporter::VisitExtVectorType(ExtVectorType *T) {
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 2fa84f3..a08ee1a 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -227,12 +227,13 @@
 }
 
 void TypePrinter::PrintVector(const VectorType *T, std::string &S) { 
-  if (T->isAltiVec()) {
-    if (T->isPixel())
+  if (T->getAltiVecSpecific() != VectorType::NotAltiVec) {
+    if (T->getAltiVecSpecific() == VectorType::Pixel)
       S = "__vector __pixel " + S;
     else {
       Print(T->getElementType(), S);
-      S = "__vector " + S;
+      S = ((T->getAltiVecSpecific() == VectorType::Bool)
+           ? "__vector __bool " : "__vector ") + S;
     }
   } else {
     // FIXME: We prefer to print the size directly here, but have no way
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index e1e2f10..01838f9 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1322,12 +1322,20 @@
 }
 
 // GNU extension: vector types
-// <type>        ::= <vector-type>
-// <vector-type> ::= Dv <positive dimension number> _ <element type>
-//               ::= Dv [<dimension expression>] _ <element type>
+// <type>                  ::= <vector-type>
+// <vector-type>           ::= Dv <positive dimension number> _
+//                                    <extended element type>
+//                         ::= Dv [<dimension expression>] _ <element type>
+// <extended element type> ::= <element type>
+//                         ::= p # AltiVec vector pixel
 void CXXNameMangler::mangleType(const VectorType *T) {
   Out << "Dv" << T->getNumElements() << '_';
-  mangleType(T->getElementType());
+  if (T->getAltiVecSpecific() == VectorType::Pixel)
+    Out << 'p';
+  else if (T->getAltiVecSpecific() == VectorType::Bool)
+    Out << 'b';
+  else
+    mangleType(T->getElementType());
 }
 void CXXNameMangler::mangleType(const ExtVectorType *T) {
   mangleType(static_cast<const VectorType*>(T));
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index b83445b..97c4d38 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2060,20 +2060,20 @@
   }
 
   case pch::TYPE_VECTOR: {
-    if (Record.size() != 4) {
+    if (Record.size() != 3) {
       Error("incorrect encoding of vector type in PCH file");
       return QualType();
     }
 
     QualType ElementType = GetType(Record[0]);
     unsigned NumElements = Record[1];
-    bool AltiVec = Record[2];
-    bool Pixel = Record[3];
-    return Context->getVectorType(ElementType, NumElements, AltiVec, Pixel);
+    unsigned AltiVecSpec = Record[2];
+    return Context->getVectorType(ElementType, NumElements,
+                                  (VectorType::AltiVecSpecific)AltiVecSpec);
   }
 
   case pch::TYPE_EXT_VECTOR: {
-    if (Record.size() != 4) {
+    if (Record.size() != 3) {
       Error("incorrect encoding of extended vector type in PCH file");
       return QualType();
     }
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 1fb9085..a55684a 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -128,8 +128,7 @@
 void PCHTypeWriter::VisitVectorType(const VectorType *T) {
   Writer.AddTypeRef(T->getElementType(), Record);
   Record.push_back(T->getNumElements());
-  Record.push_back(T->isAltiVec());
-  Record.push_back(T->isPixel());
+  Record.push_back(T->getAltiVecSpecific());
   Code = pch::TYPE_VECTOR;
 }
 
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 5dc08b3..2f328b0 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -253,7 +253,8 @@
     return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
   TypeSpecWidth = W;
   TSWLoc = Loc;
-  if (TypeAltiVecVector && ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
+  if (TypeAltiVecVector && !TypeAltiVecBool &&
+      ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
     PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
     DiagID = diag::warn_vector_long_decl_spec_combination;
     return true;
@@ -290,13 +291,18 @@
     DiagID = diag::err_invalid_decl_spec_combination;
     return true;
   }
+  if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
+    TypeAltiVecBool = true;
+    TSTLoc = Loc;
+    return false;
+  }
   TypeSpecType = T;
   TypeRep = Rep;
   TSTLoc = Loc;
   TypeSpecOwned = Owned;
-  if (TypeAltiVecVector && (TypeSpecType == TST_double)) {
+  if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
     PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
-    DiagID = diag::err_invalid_vector_double_decl_spec_combination;
+    DiagID = diag::err_invalid_vector_decl_spec;
     return true;
   }
   return false;
@@ -316,14 +322,12 @@
 
 bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
                           const char *&PrevSpec, unsigned &DiagID) {
-  if (!TypeAltiVecVector || (TypeSpecType != TST_unspecified)) {
+  if (!TypeAltiVecVector || TypeAltiVecPixel ||
+      (TypeSpecType != TST_unspecified)) {
     PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
     DiagID = diag::err_invalid_pixel_decl_spec_combination;
     return true;
   }
-  TypeSpecType = TST_int;
-  TypeSpecSign = TSS_unsigned;
-  TypeSpecWidth = TSW_short;
   TypeAltiVecPixel = isAltiVecPixel;
   TSTLoc = Loc;
   return false;
@@ -438,6 +442,42 @@
   // Check the type specifier components first.
   SourceManager &SrcMgr = PP.getSourceManager();
 
+  // Validate and finalize AltiVec vector declspec.
+  if (TypeAltiVecVector) {
+    if (TypeAltiVecBool) {
+      // Sign specifiers are not allowed with vector bool. (PIM 2.1)
+      if (TypeSpecSign != TSS_unspecified) {
+        Diag(D, TSSLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+          << getSpecifierName((TSS)TypeSpecSign);
+      }
+
+      // Only char/int are valid with vector bool. (PIM 2.1)
+      if ((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
+          (TypeSpecType != TST_int) || TypeAltiVecPixel) {
+        Diag(D, TSTLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+          << (TypeAltiVecPixel ? "__pixel" :
+                                 getSpecifierName((TST)TypeSpecType));
+      }
+
+      // Only 'short' is valid with vector bool. (PIM 2.1)
+      if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
+        Diag(D, TSWLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
+          << getSpecifierName((TSW)TypeSpecWidth);
+
+      // Elements of vector bool are interpreted as unsigned. (PIM 2.1)
+      if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
+          (TypeSpecWidth != TSW_unspecified))
+        TypeSpecSign = TSS_unsigned;
+    }
+
+    if (TypeAltiVecPixel) {
+      //TODO: perform validation
+      TypeSpecType = TST_int;
+      TypeSpecSign = TSS_unsigned;
+      TypeSpecWidth = TSW_short;
+    }
+  }
+
   // signed/unsigned are only valid with int/char/wchar_t.
   if (TypeSpecSign != TSS_unspecified) {
     if (TypeSpecType == TST_unspecified)
@@ -513,7 +553,6 @@
     ClearStorageClassSpecs();
   }
 
-
   // Okay, now we can infer the real type.
 
   // TODO: return "auto function" and other bad things based on the real type.
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d926487..b61b4d6 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -782,7 +782,8 @@
       return ExprError();
     } else if (numElements != numResElements) {
       QualType eltType = LHSType->getAs<VectorType>()->getElementType();
-      resType = Context.getVectorType(eltType, numResElements, false, false);
+      resType = Context.getVectorType(eltType, numResElements,
+                                      VectorType::NotAltiVec);
     }
   }
 
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 48c17cd..244f218 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -383,8 +383,12 @@
   } else if (DS.isTypeAltiVecVector()) {
     unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
     assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
-    Result = Context.getVectorType(Result, 128/typeSize, true,
-      DS.isTypeAltiVecPixel());
+    VectorType::AltiVecSpecific AltiVecSpec = VectorType::AltiVec;
+    if (DS.isTypeAltiVecPixel())
+      AltiVecSpec = VectorType::Pixel;
+    else if (DS.isTypeAltiVecBool())
+      AltiVecSpec = VectorType::Bool;
+    Result = Context.getVectorType(Result, 128/typeSize, AltiVecSpec);
   }
 
   assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
@@ -1162,7 +1166,8 @@
         }
 
         if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
-          // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
+          // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
+          // definition.
           Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
           D.setInvalidType(true);
           break;
@@ -1880,7 +1885,8 @@
 /// The raw attribute should contain precisely 1 argument, the vector size for
 /// the variable, measured in bytes. If curType and rawAttr are well formed,
 /// this routine will return a new vector type.
-static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) {
+static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+                                 Sema &S) {
   // Check the attribute arugments.
   if (Attr.getNumArgs() != 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
@@ -1923,7 +1929,8 @@
 
   // Success! Instantiate the vector type, the number of elements is > 0, and
   // not required to be a power of 2, unlike GCC.
-  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false);
+  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
+                                    VectorType::NotAltiVec);
 }
 
 void ProcessTypeAttributeList(Sema &S, QualType &Result,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index d959f1c..b2a4059 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -442,7 +442,7 @@
   /// By default, performs semantic analysis when building the vector type.
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
-    bool IsAltiVec, bool IsPixel);
+    VectorType::AltiVecSpecific AltiVecSpec);
 
   /// \brief Build a new extended vector type given the element type and
   /// number of elements.
@@ -2811,7 +2811,7 @@
   if (getDerived().AlwaysRebuild() ||
       ElementType != T->getElementType()) {
     Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
-      T->isAltiVec(), T->isPixel());
+      T->getAltiVecSpecific());
     if (Result.isNull())
       return QualType();
   }
@@ -6345,11 +6345,10 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
-                                       unsigned NumElements,
-                                       bool IsAltiVec, bool IsPixel) {
+                                     unsigned NumElements,
+                                     VectorType::AltiVecSpecific AltiVecSpec) {
   // FIXME: semantic checking!
-  return SemaRef.Context.getVectorType(ElementType, NumElements,
-                                       IsAltiVec, IsPixel);
+  return SemaRef.Context.getVectorType(ElementType, NumElements, AltiVecSpec);
 }
 
 template<typename Derived>