[cfe-commits] [PATCH] AltiVec vector support - stage 1

Douglas Gregor dgregor at apple.com
Fri Dec 18 14:05:45 PST 2009


Hi John,

On Dec 16, 2009, at 11:45 AM, John Thompson wrote:

> Nudge nudge...
>
> I know I need to do an error message checking test too.  This is  
> just a start, to avoid too much change at once, and to make sure I'm  
> on the right track.  Please review it before it gets too stale.
>
> -John
>
> On Fri, Dec 11, 2009 at 8:03 PM, John Thompson <john.thompson.jtsoftware at gmail.com 
> > wrote:
> Here's a stab a the first stage of adding AltiVec vector support,  
> supporting the AltiVec types __vector, vector, __pixel, pixel, and  
> bool.  I've also enclosed a couple of tests for it for the test/ 
> Parser directory.
>
> Some of it might be iffy, but I hope you can help me get it into  
> shape with your feedback.
>
> I added a couple of flags to the DeclSpec class to help me know when  
> the types are used, TypeAltiVecVector and TypeAltiVecPixel.  The  
> AltiVec standard doesn't say much about pixel, other than it is used  
> as "__vector __pixel", and that it represents 8 unsigned shorts.   
> Therefore, instead of making a new TST, I made it more like an alias  
> via the TypeAltiVecPixel flag.
>
> I also added two corresponding flags to the VectorType class (and  
> the getVectorType function).  Currently, these mainly just help with  
> printing, but maybe there will be a need to distinguish down the  
> road.  This is kind of an iffy part, because there were a couple of  
> places where I don't know if the vector involved is an AltiVec  
> vector, and the flags are used in the type look up.
>
> Per the previous conversation, I made __vector and __pixel true  
> keywords if -faltivec is used, and vector and pixel are context- 
> sensitive keywords.  The AltiVec standard also specifies that bool  
> is a keyword in C, so I diddled the token flags a bit for that too.
>
> I put the Token patching code in inline functions, so I hope the  
> performance impact is not too bad.
> There's probably some holes in the testing, i.e. sizeof.  But,  
> because I'm piggy-backing on the existing vectors, I'm hoping most  
> things will still just work.
>
> I'm not sure what the next stage should be, the built-in functions?
>
> Thanks.
>
> -John


+def err_invalid_pixel_decl_spec_combination : Error<
+  "\"__pixel\" must be preceeded by \"__vector\".  '%0' declaration  
specifier not allowed here">;

Typo "preceeded".

Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 91204)
+++ include/clang/AST/Type.h	(working copy)
@@ -1576,7 +1576,8 @@

  /// 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
+/// bytes; or from an Altivec __vector or vector declaration.
+/// 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:
@@ -1586,13 +1587,21 @@
    /// NumElements - The number of elements in the vector.
    unsigned NumElements;

-  VectorType(QualType vecType, unsigned nElements, QualType  
canonType) :
+  /// AltiVec - True if this is for an Altivec vector.
+  bool AltiVec;
+
+  /// Pixel - True if this is for an Altivec vector pixel.
+  bool Pixel;
+

I think this is right, but I want to check: are AltiVec vectors more  
like GCC's vectors (handled by VectorType) or more like OpenCL's  
vectors (handled by ExtVectorType)? OpenCL vectors are mainly GCC's  
vectors + the swizzling syntax like "myvec.xy".

Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 91204)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -320,6 +320,80 @@
    /// annotated.
    bool TryAnnotateCXXScopeToken(bool EnteringContext = false);

+  /// TryAltiVecToken - Check for context-sensitive AltiVec  
identifier tokens,
+  /// replacing them with the non-context-sensitive keywords.  This  
returns
+  /// true if the token was replaced.
+  bool TryAltiVecToken(DeclSpec &DS) {
+    if (getLang().AltiVec) {
+      if (Tok.getIdentifierInfo()->isStr<7>("vector")) {

It would be more efficient just to keep the IdentiferInfo * for the  
identifiers "vector" and "pixel" in the parser (only when AltiVec is  
enabled, of course), then do a pointer comparison rather than a string  
comparison.

+        const Token &nextToken = NextToken();

Tokens are small; it's best to just copy them, e.g.,

   Token nextToken = NextToken();

+        switch (nextToken.getKind()) {
+          case tok::kw_short:
+          case tok::kw_long:
+          case tok::kw_signed:
+          case tok::kw_unsigned:
+          case tok::kw_void:
+          case tok::kw_char:
+          case tok::kw_int:
+          case tok::kw_float:
+          case tok::kw_double:
+          case tok::kw_bool:
+          case tok::kw___pixel:
+            Tok.setKind(tok::kw___vector);
+            return true;
+          case tok::identifier:
+            if (nextToken.getIdentifierInfo()->isStr<6>("pixel")) {
+              Tok.setKind(tok::kw___vector);
+              return true;
+            }

By changing the current token, we lose track of whether we saw  
"vector" or "__vector"; I guess it doesn't really matter. Still,  
wouldn't it be easier just to update the DeclSpec at this point?

Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 91204)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -339,6 +339,11 @@
      if (TheSema.getLangOptions().Freestanding)
        TheSema.Diag(DS.getTypeSpecComplexLoc(),  
diag::ext_freestanding_complex);
      Result = Context.getComplexType(Result);
+  } 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());
    }

At some point, we'll need more semantic checking here, e.g., to ignore  
"long long" and complain about the deprecation of "long", if I'm to  
believe

	http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=/com.ibm.vacpp6m.doc/language/ref/clrc03altivec_types.htm

Or perhaps there's some actual AltiVec specification I could use to  
help understand this stuff better?

Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp	(revision 91204)
+++ lib/AST/TypePrinter.cpp	(working copy)
@@ -240,15 +240,24 @@
  }

  void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
-  // FIXME: We prefer to print the size directly here, but have no way
-  // to get the size of the type.
-  Print(T->getElementType(), S);
-  std::string V = "__attribute__((__vector_size__(";
-  V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
-  std::string ET;
-  Print(T->getElementType(), ET);
-  V += " * sizeof(" + ET + ")))) ";
-  S = V + S;
+  if (T->isAltiVec()) {
+    if (T->isPixel())
+      S = "vector pixel " + S;
+    else {
+      Print(T->getElementType(), S);
+      S = "vector " + S;
+    }

It would probably be better to print with "__vector" and "__pixel",  
since those keywords are always available.

Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 91204)
+++ include/clang/AST/ASTContext.h	(working copy)
@@ -498,7 +498,8 @@

    /// 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);
+  QualType getVectorType(QualType VectorType, unsigned NumElts,
+                         bool AltiVec, bool IsPixel);

Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp	(revision 91204)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -1590,7 +1590,8 @@

  /// 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) {
+QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
+                                   bool IsAltiVec, bool IsPixel) {
    BuiltinType *baseType;

    baseType = dyn_cast<BuiltinType>(getCanonicalType 
(vecType).getTypePtr());
@@ -1598,7 +1599,8 @@

    // Check if we've already instantiated a vector of this type.
    llvm::FoldingSetNodeID ID;
-  VectorType::Profile(ID, vecType, NumElts, Type::Vector);
+  VectorType::Profile(ID, vecType, NumElts, Type::Vector,
+    IsAltiVec, IsPixel);
    void *InsertPos = 0;
    if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID,  
InsertPos))
      return QualType(VTP, 0);
@@ -1607,14 +1609,15 @@
    // so fill in the canonical type field.
    QualType Canonical;
    if (!vecType.isCanonical()) {
-    Canonical = getVectorType(getCanonicalType(vecType), NumElts);
+    Canonical = getVectorType(getCanonicalType(vecType),
+      NumElts, IsAltiVec, IsPixel);

This makes it so that AltiVec vectors are completely distinct types  
from equivalently-sized vectors (as declared with __attribute__ 
((vector_size(blah))). If we want to be able to cast between AltiVec  
vectors and GCC-style vectors, we'll need to add type-compatibility  
logic (for C) and type-conversion logic (for C++). I don't know which  
way is correct... how does GCC handle compatibility between the  
various kinds of vectors? We'll need to follow its lead.

Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 91204)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -393,6 +393,12 @@
    }

    if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
+    // If attributes are present, parse them now.
+    if (Tok.is(tok::kw___attribute)) {
+      SourceLocation Loc;
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
+      D.AddAttributes(AttrList, Loc);
+    }

This seems totally unrelated to AltiVec vectors?

+bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel,  
SourceLocation Loc,
+                          const char *&PrevSpec, unsigned &DiagID) {
+  if (!TypeAltiVecVector || (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;
+}
+

pixel is an unsigned short? Weird.

Thanks for working on this!

	- Doug
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20091218/54a72ec0/attachment.html>


More information about the cfe-commits mailing list