From: John Thompson Date: Fri, 5 Feb 2010 00:12:22 +0000 (+0000) Subject: First stage of adding AltiVec support X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82287d19ded35248c4ce6a425ce74116a13ce44e;p=clang First stage of adding AltiVec support git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95335 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 18b09a2b21..6fa6e30deb 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -502,7 +502,8 @@ public: /// 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); /// getExtVectorType - Return the unique reference to an extended vector type /// of the specified element type and size. VectorType must be a built-in diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index fa5d3e105f..4e213ed785 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1594,7 +1594,8 @@ public: /// 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: @@ -1604,13 +1605,21 @@ protected: /// 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; + + VectorType(QualType vecType, unsigned nElements, QualType canonType, + bool isAltiVec, bool isPixel) : Type(Vector, canonType, vecType->isDependentType()), - ElementType(vecType), NumElements(nElements) {} + ElementType(vecType), NumElements(nElements), + AltiVec(isAltiVec), Pixel(isPixel) {} VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType) + QualType canonType, bool isAltiVec, bool isPixel) : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), - NumElements(nElements) {} + NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} friend class ASTContext; // ASTContext creates these. public: @@ -1620,14 +1629,22 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + bool isAltiVec() const { return AltiVec; } + + bool isPixel() const { return Pixel; } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getNumElements(), getTypeClass()); + Profile(ID, getElementType(), getNumElements(), getTypeClass(), + AltiVec, Pixel); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, - unsigned NumElements, TypeClass TypeClass) { + unsigned NumElements, TypeClass TypeClass, + bool isAltiVec, bool isPixel) { ID.AddPointer(ElementType.getAsOpaquePtr()); ID.AddInteger(NumElements); ID.AddInteger(TypeClass); + ID.AddBoolean(isAltiVec); + ID.AddBoolean(isPixel); } virtual Linkage getLinkage() const; @@ -1645,7 +1662,7 @@ public: /// points, colors, and textures (modeled after OpenGL Shading Language). class ExtVectorType : public VectorType { ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : - VectorType(ExtVector, vecType, nElements, canonType) {} + VectorType(ExtVector, vecType, nElements, canonType, false, false) {} friend class ASTContext; // ASTContext creates these. public: static int getPointAccessorIdx(char c) { diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index dc83e87e96..04e3daffe7 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -160,6 +160,14 @@ def err_typename_invalid_functionspec : Error< "type name does not allow function specifier to be specified">; def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; +def err_invalid_vector_decl_spec_combination : Error< + "cannot combine with previous '%0' declaration specifier. \"__vector\" must be first">; +def err_invalid_pixel_decl_spec_combination : Error< + "\"__pixel\" must be preceded by \"__vector\". '%0' declaration specifier not allowed here">; +def err_invalid_vector_double_decl_spec_combination : Error< + "cannot use \"double\" with \"__vector\"">; +def warn_vector_long_decl_spec_combination : Warning< + "Use of \"long\" with \"__vector\" is deprecated">; def err_friend_invalid_in_context : Error< "'friend' used outside of class">; def err_unknown_typename : Error< diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 9e54762add..3b60b689ae 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -46,6 +46,7 @@ namespace clang { TST_decimal32, // _Decimal32 TST_decimal64, // _Decimal64 TST_decimal128, // _Decimal128 + TST_pixel, // AltiVec TST_enum, TST_union, TST_struct, diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index bb022f1175..522ac13b4e 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -227,7 +227,7 @@ KEYWORD(__func__ , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) -KEYWORD(bool , BOOLSUPPORT) +KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC) KEYWORD(catch , KEYCXX) KEYWORD(class , KEYCXX) KEYWORD(const_cast , KEYCXX) @@ -235,7 +235,7 @@ KEYWORD(delete , KEYCXX) KEYWORD(dynamic_cast , KEYCXX) KEYWORD(explicit , KEYCXX) KEYWORD(export , KEYCXX) -KEYWORD(false , BOOLSUPPORT) +KEYWORD(false , BOOLSUPPORT|KEYALTIVEC) KEYWORD(friend , KEYCXX) KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) @@ -249,7 +249,7 @@ KEYWORD(static_cast , KEYCXX) KEYWORD(template , KEYCXX) KEYWORD(this , KEYCXX) KEYWORD(throw , KEYCXX) -KEYWORD(true , BOOLSUPPORT) +KEYWORD(true , BOOLSUPPORT|KEYALTIVEC) KEYWORD(try , KEYCXX) KEYWORD(typename , KEYCXX) KEYWORD(typeid , KEYCXX) @@ -340,6 +340,10 @@ KEYWORD(__ptr64 , KEYALL) KEYWORD(__w64 , KEYALL) KEYWORD(__forceinline , KEYALL) +// Altivec Extension. +KEYWORD(__vector , KEYALTIVEC) +KEYWORD(__pixel , KEYALTIVEC) + // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. ALIAS("__attribute__", __attribute, KEYALL) diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index f923b5e910..c3fc952bdd 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -113,6 +113,7 @@ public: static const TST TST_decimal32 = clang::TST_decimal32; static const TST TST_decimal64 = clang::TST_decimal64; static const TST TST_decimal128 = clang::TST_decimal128; + static const TST TST_pixel = clang::TST_pixel; static const TST TST_enum = clang::TST_enum; static const TST TST_union = clang::TST_union; static const TST TST_struct = clang::TST_struct; @@ -153,6 +154,8 @@ private: /*TSC*/unsigned TypeSpecComplex : 2; /*TSS*/unsigned TypeSpecSign : 2; /*TST*/unsigned TypeSpecType : 5; + bool TypeAltiVecVector : 1; + bool TypeAltiVecPixel : 1; bool TypeSpecOwned : 1; // type-qualifiers @@ -193,7 +196,7 @@ private: SourceRange Range; SourceLocation StorageClassSpecLoc, SCS_threadLoc; - SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; + SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; SourceRange TypeofParensRange; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; @@ -213,6 +216,8 @@ public: TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified), TypeSpecType(TST_unspecified), + TypeAltiVecVector(false), + TypeAltiVecPixel(false), TypeSpecOwned(false), TypeQualifiers(TSS_unspecified), FS_inline_specified(false), @@ -250,6 +255,8 @@ public: TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } TST getTypeSpecType() const { return (TST)TypeSpecType; } + bool isTypeAltiVecVector() const { return TypeAltiVecVector; } + bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } bool isTypeSpecOwned() const { return TypeSpecOwned; } void *getTypeRep() const { return TypeRep; } CXXScopeSpec &getTypeSpecScope() { return TypeScope; } @@ -260,6 +267,7 @@ public: SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } + SourceLocation getAltiVecLoc() const { return AltiVecLoc; } SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } @@ -344,6 +352,10 @@ public: unsigned &DiagID); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, void *Rep = 0, bool Owned = false); + bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); + bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecError(); void UpdateTypeRep(void *Rep) { TypeRep = Rep; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 71aa38a155..f4d3d3e54d 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -81,6 +81,11 @@ class Parser { /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. IdentifierInfo *Ident_super; + /// Ident_vector and Ident_pixel - cached IdentifierInfo's for + /// "vector" and "pixel" fast comparison. Only present if + /// AltiVec enabled. + IdentifierInfo *Ident_vector; + IdentifierInfo *Ident_pixel; llvm::OwningPtr PackHandler; llvm::OwningPtr UnusedHandler; @@ -320,6 +325,81 @@ private: /// 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, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID, bool &isInvalid) { + if (getLang().AltiVec) { + if (Tok.getIdentifierInfo() == Ident_vector) { + const 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: + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + return true; + case tok::identifier: + if (nextToken.getIdentifierInfo() == Ident_pixel) { + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + return true; + } + break; + default: + break; + } + } else if ((Tok.getIdentifierInfo() == Ident_pixel) && + DS.isTypeAltiVecVector()) { + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); + return true; + } + } + return false; + } + + /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector + /// identifier token, replacing it with the non-context-sensitive __vector. + /// This returns true if the token was replaced. + bool TryAltiVecVectorToken() { + if (getLang().AltiVec) { + if (Tok.getIdentifierInfo() == Ident_vector) { + const 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() == Ident_pixel) { + Tok.setKind(tok::kw___vector); + return true; + } + break; + default: + break; + } + } + } + return false; + } + /// TentativeParsingAction - An object that is used as a kind of "tentative /// parsing transaction". It gets instantiated to mark the token position and /// after the token consumption is done, Commit() or Revert() is called to diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 676be72787..b61ce8e529 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1610,7 +1610,8 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy, /// 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(getCanonicalType(vecType).getTypePtr()); @@ -1618,7 +1619,8 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) { // 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); @@ -1626,15 +1628,16 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) { // 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 = getVectorType(getCanonicalType(vecType), NumElts); + if (!vecType.isCanonical() || IsAltiVec || IsPixel) { + Canonical = getVectorType(getCanonicalType(vecType), + NumElts, false, false); // 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); + VectorType(vecType, NumElts, Canonical, IsAltiVec, IsPixel); VectorTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); @@ -1650,7 +1653,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; - VectorType::Profile(ID, vecType, NumElts, Type::ExtVector); + VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, false, false); void *InsertPos = 0; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -4636,7 +4639,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { // Turn <4 x signed int> -> <4 x unsigned int> if (const VectorType *VTy = T->getAs()) return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), - VTy->getNumElements()); + VTy->getNumElements(), VTy->isAltiVec(), VTy->isPixel()); // For enums, we return the unsigned version of the base type. if (const EnumType *ETy = T->getAs()) @@ -4793,7 +4796,8 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, Str = End; QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false); - Type = Context.getVectorType(ElementType, NumElements); + // FIXME: Don't know what to do about AltiVec. + Type = Context.getVectorType(ElementType, NumElements, false, false); break; } case 'X': { diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 597ab37d2b..5b621cf728 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -225,15 +225,24 @@ void TypePrinter::PrintDependentSizedExtVector( } 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; + } + } else { + // 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; + } } void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 401e6cba06..16a61b7156 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -68,7 +68,8 @@ namespace { KEYCXX0X = 8, KEYGNU = 16, KEYMS = 32, - BOOLSUPPORT = 64 + BOOLSUPPORT = 64, + KEYALTIVEC = 128 }; } @@ -91,6 +92,7 @@ static void AddKeyword(const char *Keyword, unsigned KWLen, else if (LangOpts.GNUMode && (Flags & KEYGNU)) AddResult = 1; else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1; else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2; + else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2; // Don't add this keyword if disabled in this language. if (AddResult == 0) return; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index bd93cf6b08..1ed5260a88 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1880,18 +1880,20 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { } case pch::TYPE_VECTOR: { - if (Record.size() != 2) { + if (Record.size() != 4) { Error("incorrect encoding of vector type in PCH file"); return QualType(); } QualType ElementType = GetType(Record[0]); unsigned NumElements = Record[1]; - return Context->getVectorType(ElementType, NumElements); + bool AltiVec = Record[2]; + bool Pixel = Record[3]; + return Context->getVectorType(ElementType, NumElements, AltiVec, Pixel); } case pch::TYPE_EXT_VECTOR: { - if (Record.size() != 2) { + if (Record.size() != 4) { 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 caf1ce47a1..a87b8cde2c 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -128,6 +128,8 @@ void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { 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()); Code = pch::TYPE_VECTOR; } diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index 9e5f5a2ac0..0f1063eb3c 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -192,6 +192,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_decimal32: return "_Decimal32"; case DeclSpec::TST_decimal64: return "_Decimal64"; case DeclSpec::TST_decimal128: return "_Decimal128"; + case DeclSpec::TST_pixel: return "__pixel"; case DeclSpec::TST_enum: return "enum"; case DeclSpec::TST_class: return "class"; case DeclSpec::TST_union: return "union"; @@ -253,6 +254,11 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); TypeSpecWidth = W; TSWLoc = Loc; + if (TypeAltiVecVector && ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::warn_vector_long_decl_spec_combination; + return true; + } return false; } @@ -289,6 +295,38 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, TypeRep = Rep; TSTLoc = Loc; TypeSpecOwned = Owned; + if (TypeAltiVecVector && (TypeSpecType == TST_double)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_double_decl_spec_combination; + return true; + } + return false; +} + +bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_decl_spec_combination; + return true; + } + TypeAltiVecVector = isAltiVecVector; + AltiVecLoc = Loc; + return false; +} + +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; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9960238300..7856e62f04 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1029,6 +1029,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.hasTypeSpecifier()) goto DoneWithDeclSpec; + // Check for need to substitute AltiVec keyword tokens. + if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid)) + break; + // It has to be available as a typedef too! TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), CurScope); @@ -1270,6 +1274,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, DiagID); break; + case tok::kw___vector: + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + break; + case tok::kw___pixel: + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); + break; // class-specifier: case tok::kw_class: @@ -1395,6 +1405,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// [OBJC] class-name objc-protocol-refs[opt] [TODO] /// [OBJC] typedef-name objc-protocol-refs[opt] [TODO] /// [C++0x] 'decltype' ( expression ) +/// [AltiVec] '__vector' bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, const char *&PrevSpec, unsigned &DiagID, @@ -1404,6 +1415,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, switch (Tok.getKind()) { case tok::identifier: // foo::bar + // Check for need to substitute AltiVec keyword tokens. + if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid)) + break; + // Fall through. case tok::kw_typename: // typename foo::bar // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. @@ -1520,7 +1535,13 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, DiagID); break; - + case tok::kw___vector: + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + break; + case tok::kw___pixel: + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); + break; + // class-specifier: case tok::kw_class: case tok::kw_struct: @@ -1987,6 +2008,9 @@ bool Parser::isTypeSpecifierQualifier() { default: return false; case tok::identifier: // foo::bar + if (TryAltiVecVectorToken()) + return true; + // Fall through. case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. @@ -2032,6 +2056,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw__Decimal32: case tok::kw__Decimal64: case tok::kw__Decimal128: + case tok::kw___vector: // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: @@ -2072,7 +2097,9 @@ bool Parser::isDeclarationSpecifier() { // Unfortunate hack to support "Class.factoryMethod" notation. if (getLang().ObjC1 && NextToken().is(tok::period)) return false; - // Fall through + if (TryAltiVecVectorToken()) + return true; + // Fall through. case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just @@ -2123,6 +2150,7 @@ bool Parser::isDeclarationSpecifier() { case tok::kw__Decimal32: case tok::kw__Decimal64: case tok::kw__Decimal128: + case tok::kw___vector: // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: @@ -2768,7 +2796,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Alternatively, this parameter list may be an identifier list form for a // K&R-style function: void foo(a,b,c) - if (!getLang().CPlusPlus && Tok.is(tok::identifier)) { + if (!getLang().CPlusPlus && Tok.is(tok::identifier) + && !TryAltiVecVectorToken()) { if (!TryAnnotateTypeOrScopeToken()) { // K&R identifier lists can't have typedefs as identifiers, per // C99 6.7.5.3p11. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 669575c4f0..c6091367fd 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -780,6 +780,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: + case tok::kw___vector: case tok::annot_typename: { if (!getLang().CPlusPlus) { Diag(Tok, diag::err_expected_expression); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 51c56706bb..6251a2f367 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -672,6 +672,11 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, Parser::TPResult Parser::isCXXDeclarationSpecifier() { switch (Tok.getKind()) { case tok::identifier: // foo::bar + // Check for need to substitute AltiVec __vector keyword + // for "vector" identifier. + if (TryAltiVecVectorToken()) + return TPResult::True(); + // Fall through. case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. @@ -750,6 +755,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___ptr64: case tok::kw___forceinline: return TPResult::True(); + + // AltiVec + case tok::kw___vector: + return TPResult::True(); case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed // We've already annotated a scope; try to annotate a type. diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 63b0a27c08..f15b39a83e 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -346,6 +346,11 @@ void Parser::Initialize() { } Ident_super = &PP.getIdentifierTable().get("super"); + + if (getLang().AltiVec) { + Ident_vector = &PP.getIdentifierTable().get("vector"); + Ident_pixel = &PP.getIdentifierTable().get("pixel"); + } } /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8833792494..60f3b19060 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -343,6 +343,11 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ if (TheSema.getLangOptions().Freestanding) TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); Result = Context.getComplexType(Result); + } else if (DS.isTypeAltiVecVector()) { + unsigned typeSize = static_cast(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()); } assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary && @@ -1753,7 +1758,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S // 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); + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false); } void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index b1b85e5928..8bac64e127 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -428,7 +428,8 @@ public: /// /// 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); + QualType RebuildVectorType(QualType ElementType, unsigned NumElements, + bool IsAltiVec, bool IsPixel); /// \brief Build a new extended vector type given the element type and /// number of elements. @@ -2472,7 +2473,8 @@ QualType TreeTransform::TransformVectorType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || ElementType != T->getElementType()) { - Result = getDerived().RebuildVectorType(ElementType, T->getNumElements()); + Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(), + T->isAltiVec(), T->isPixel()); if (Result.isNull()) return QualType(); } @@ -5421,9 +5423,11 @@ TreeTransform::RebuildDependentSizedArrayType(QualType ElementType, template QualType TreeTransform::RebuildVectorType(QualType ElementType, - unsigned NumElements) { + unsigned NumElements, + bool IsAltiVec, bool IsPixel) { // FIXME: semantic checking! - return SemaRef.Context.getVectorType(ElementType, NumElements); + return SemaRef.Context.getVectorType(ElementType, NumElements, + IsAltiVec, IsPixel); } template diff --git a/test/Parser/altivec.c b/test/Parser/altivec.c new file mode 100644 index 0000000000..99544ea5c1 --- /dev/null +++ b/test/Parser/altivec.c @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -faltivec -fsyntax-only -verify %s + +__vector char vv_c; +__vector signed char vv_sc; +__vector unsigned char vv_uc; +__vector short vv_s; +__vector signed short vv_ss; +__vector unsigned short vv_us; +__vector short int vv_si; +__vector signed short int vv_ssi; +__vector unsigned short int vv_usi; +__vector int vv_i; +__vector signed int vv_sint; +__vector unsigned int vv_ui; +__vector float vv_f; +__vector bool vv_b; +__vector __pixel vv_p; +__vector pixel vv__p; +__vector int vf__r(); +void vf__a(__vector int a); +void vf__a2(int b, __vector int a); + +vector char v_c; +vector signed char v_sc; +vector unsigned char v_uc; +vector short v_s; +vector signed short v_ss; +vector unsigned short v_us; +vector short int v_si; +vector signed short int v_ssi; +vector unsigned short int v_usi; +vector int v_i; +vector signed int v_sint; +vector unsigned int v_ui; +vector float v_f; +vector bool v_b; +vector __pixel v_p; +vector pixel v__p; +vector int f__r(); +void f_a(vector int a); +void f_a2(int b, vector int a); + +// These should have warnings. +__vector long vv_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector signed long vv_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector unsigned long vv_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector long int vv_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector signed long int vv_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector unsigned long int vv_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector long v_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector signed long v_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector unsigned long v_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector long int v_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector signed long int v_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector unsigned long int v_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} + +// These should have errors. +__vector double vv_d; // expected-error {{cannot use "double" with "__vector"}} +__vector double vv_d; // expected-error {{cannot use "double" with "__vector"}} +vector double v_d; // expected-error {{cannot use "double" with "__vector"}} +vector double v_d; // expected-error {{cannot use "double" with "__vector"}} +__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} + +void f() { + __vector unsigned int v = {0,0,0,0}; + __vector int v__cast = (__vector int)v; + __vector int v_cast = (vector int)v; + __vector char vb_cast = (vector char)v; + + // Check some casting between gcc and altivec vectors. + #define gccvector __attribute__((vector_size(16))) + gccvector unsigned int gccv = {0,0,0,0}; + gccvector unsigned int gccv1 = gccv; + gccvector int gccv2 = (gccvector int)gccv; + gccvector unsigned int gccv3 = v; + __vector unsigned int av = gccv; + __vector int avi = (__vector int)gccv; + gccvector unsigned int gv = v; + gccvector int gvi = (gccvector int)v; + __attribute__((vector_size(8))) unsigned int gv8; + gv8 = gccv; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int', expected '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} + av = gv8; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int', expected '__vector unsigned int'}} + + v = gccv; + __vector unsigned int tv = gccv; + gccv = v; + gccvector unsigned int tgv = v; +} diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp new file mode 100644 index 0000000000..a26eee4ef4 --- /dev/null +++ b/test/Parser/cxx-altivec.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -faltivec -fsyntax-only -verify %s + +// This is the same as the C version: + +__vector char vv_c; +__vector signed char vv_sc; +__vector unsigned char vv_uc; +__vector short vv_s; +__vector signed short vv_ss; +__vector unsigned short vv_us; +__vector short int vv_si; +__vector signed short int vv_ssi; +__vector unsigned short int vv_usi; +__vector int vv_i; +__vector signed int vv_sint; +__vector unsigned int vv_ui; +__vector float vv_f; +__vector bool vv_b; +__vector __pixel vv_p; +__vector pixel vv__p; +__vector int vf__r(); +void vf__a(__vector int a); +void vf__a2(int b, __vector int a); + +vector char v_c; +vector signed char v_sc; +vector unsigned char v_uc; +vector short v_s; +vector signed short v_ss; +vector unsigned short v_us; +vector short int v_si; +vector signed short int v_ssi; +vector unsigned short int v_usi; +vector int v_i; +vector signed int v_sint; +vector unsigned int v_ui; +vector float v_f; +vector bool v_b; +vector __pixel v_p; +vector pixel v__p; +vector int f__r(); +void f_a(vector int a); +void f_a2(int b, vector int a); + +// These should have warnings. +__vector long vv_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector signed long vv_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector unsigned long vv_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector long int vv_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector signed long int vv_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector unsigned long int vv_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector long v_l; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector signed long v_sl; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector unsigned long v_ul; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector long int v_li; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector signed long int v_sli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +vector unsigned long int v_uli; // expected-warning {{Use of "long" with "__vector" is deprecated}} +__vector long double vv_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +vector long double v_ld; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} + +// These should have errors. +__vector double vv_d1; // expected-error {{cannot use "double" with "__vector"}} +vector double v_d2; // expected-error {{cannot use "double" with "__vector"}} +__vector long double vv_ld3; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} +vector long double v_ld4; // expected-warning {{Use of "long" with "__vector" is deprecated}} expected-error {{cannot use "double" with "__vector"}} + +void f() { + __vector unsigned int v = {0,0,0,0}; + __vector int v__cast = (__vector int)v; + __vector int v_cast = (vector int)v; + __vector char vb_cast = (vector char)v; + + // Check some casting between gcc and altivec vectors. + #define gccvector __attribute__((vector_size(16))) + gccvector unsigned int gccv = {0,0,0,0}; + gccvector unsigned int gccv1 = gccv; + gccvector int gccv2 = (gccvector int)gccv; + gccvector unsigned int gccv3 = v; + __vector unsigned int av = gccv; + __vector int avi = (__vector int)gccv; + gccvector unsigned int gv = v; + gccvector int gvi = (gccvector int)v; + __attribute__((vector_size(8))) unsigned int gv8; + gv8 = gccv; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int', expected '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} + av = gv8; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int', expected '__vector unsigned int'}} + + v = gccv; + __vector unsigned int tv = gccv; + gccv = v; + gccvector unsigned int tgv = v; +} + +// Now for the C++ version: + +class vc__v { + __vector int v; + __vector int f__r(); + void f__a(__vector int a); + void f__a2(int b, __vector int a); +}; + +class c_v { + vector int v; + vector int f__r(); + void f__a(vector int a); + void f__a2(int b, vector int a); +}; +