diff options
30 files changed, 476 insertions, 0 deletions
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 44f2f8dbea..f6a7a4e431 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -1473,6 +1473,50 @@ indices specified. Query for this feature with ``__has_builtin(__builtin_shufflevector)``. +``__builtin_convertvector`` +--------------------------- + +``__builtin_convertvector`` is used to express generic vector +type-conversion operations. The input vector and the output vector +type must have the same number of elements. + +**Syntax**: + +.. code-block:: c++ + + __builtin_convertvector(src_vec, dst_vec_type) + +**Examples**: + +.. code-block:: c++ + + typedef double vector4double __attribute__((__vector_size__(32))); + typedef float vector4float __attribute__((__vector_size__(16))); + typedef short vector4short __attribute__((__vector_size__(8))); + vector4float vf; vector4short vs; + + // convert from a vector of 4 floats to a vector of 4 doubles. + __builtin_convertvector(vf, vector4double) + // equivalent to: + (vector4double) { (double) vf[0], (double) vf[1], (double) vf[2], (double) vf[3] } + + // convert from a vector of 4 shorts to a vector of 4 floats. + __builtin_convertvector(vs, vector4float) + // equivalent to: + (vector4float) { (float) vf[0], (float) vf[1], (float) vf[2], (float) vf[3] } + +**Description**: + +The first argument to ``__builtin_convertvector`` is a vector, and the second +argument is a vector type with the same number of elements as the first +argument. + +The result of ``__builtin_convertvector`` is a vector with the same element +type as the second argument, with a value defined in terms of the action of a +C-style cast applied to each element of the first argument. + +Query for this feature with ``__has_builtin(__builtin_convertvector)``. + ``__builtin_unreachable`` ------------------------- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index e82d6bb05f..8a884c0b2e 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3468,6 +3468,60 @@ public: } }; +/// ConvertVectorExpr - Clang builtin function __builtin_convertvector +/// This AST node provides support for converting a vector type to another +/// vector type of the same arity. +class ConvertVectorExpr : public Expr { +private: + Stmt *SrcExpr; + TypeSourceInfo *TInfo; + SourceLocation BuiltinLoc, RParenLoc; + + friend class ASTReader; + friend class ASTStmtReader; + explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {} + +public: + ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation BuiltinLoc, SourceLocation RParenLoc) + : Expr(ConvertVectorExprClass, DstType, VK, OK, + DstType->isDependentType(), + DstType->isDependentType() || SrcExpr->isValueDependent(), + (DstType->isInstantiationDependentType() || + SrcExpr->isInstantiationDependent()), + (DstType->containsUnexpandedParameterPack() || + SrcExpr->containsUnexpandedParameterPack())), + SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} + + /// getSrcExpr - Return the Expr to be converted. + Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } + + /// getTypeSourceInfo - Return the destination type. + TypeSourceInfo *getTypeSourceInfo() const { + return TInfo; + } + void setTypeSourceInfo(TypeSourceInfo *ti) { + TInfo = ti; + } + + /// getBuiltinLoc - Return the location of the __builtin_convertvector token. + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + + /// getRParenLoc - Return the location of final right parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConvertVectorExprClass; + } + + // Iterators + child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } +}; + /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. /// This AST node is similar to the conditional operator (?:) in C, with /// the following exceptions: diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 46adcda6e0..ac6ea67594 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2262,6 +2262,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index cb7613ce12..83f00bb1c7 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -488,6 +488,7 @@ BUILTIN(__builtin_trap, "v", "nr") BUILTIN(__builtin_debugtrap, "v", "n") BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nc") +BUILTIN(__builtin_convertvector, "v." , "nct") BUILTIN(__builtin_alloca, "v*z" , "n") // "Overloaded" Atomic operator builtins. These are overloaded to support data diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index af5c6f6099..f53ca666d5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6374,6 +6374,13 @@ def err_shufflevector_argument_too_large : Error< "index for __builtin_shufflevector must be less than the total number " "of vector elements">; +def err_convertvector_non_vector : Error< + "first argument to __builtin_convertvector must be a vector">; +def err_convertvector_non_vector_type : Error< + "second argument to __builtin_convertvector must be a vector type">; +def err_convertvector_incompatible_vector : Error< + "first two arguments to __builtin_convertvector must have the same number of elements">; + def err_vector_incorrect_num_initializers : Error< "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 0da9b34028..69851a9d52 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -162,6 +162,7 @@ def CUDAKernelCallExpr : DStmt<CallExpr>; // Clang Extensions. def ShuffleVectorExpr : DStmt<Expr>; +def ConvertVectorExpr : DStmt<Expr>; def BlockExpr : DStmt<Expr>; def OpaqueValueExpr : DStmt<Expr>; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 3f156a86a2..d763632164 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -542,6 +542,7 @@ ALIAS("_declspec" , __declspec , KEYMS) ALIAS("_pascal" , __pascal , KEYBORLAND) // Clang Extensions. +KEYWORD(__builtin_convertvector , KEYALL) ALIAS("__char16_t" , char16_t , KEYCXX) ALIAS("__char32_t" , char32_t , KEYCXX) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 573f028019..5d0f081391 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3546,6 +3546,13 @@ public: ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body, Scope *CurScope); + //===---------------------------- Clang Extensions ----------------------===// + + /// __builtin_convertvector(...) + ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); + //===---------------------------- OpenCL Features -----------------------===// /// __builtin_astype(...) @@ -7711,6 +7718,9 @@ private: public: // Used by C++ template instantiation. ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); private: bool SemaBuiltinPrefetch(CallExpr *TheCall); diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index b1e5e72ae5..03d905054a 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1186,6 +1186,8 @@ namespace clang { EXPR_GNU_NULL, /// \brief A ShuffleVectorExpr record. EXPR_SHUFFLE_VECTOR, + /// \brief A ConvertVectorExpr record. + EXPR_CONVERT_VECTOR, /// \brief BlockExpr EXPR_BLOCK, /// \brief A GenericSelectionExpr record. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index ea91fbec4f..a3a36da65f 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2843,6 +2843,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case SubstNonTypeTemplateParmExprClass: case MaterializeTemporaryExprClass: case ShuffleVectorExprClass: + case ConvertVectorExprClass: case AsTypeExprClass: // These have a side-effect if any subexpression does. break; diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 1c91af7d47..4640d7d37d 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -155,6 +155,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::OffsetOfExprClass: case Expr::CXXThrowExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: case Expr::AddrLabelExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8ca33cbd20..0fb6d42761 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -8145,6 +8145,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::BlockExprClass: case Expr::NoStmtClass: case Expr::OpaqueValueExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index a87bf1123e..3b32bdfb2b 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2603,6 +2603,7 @@ recurse: case Expr::OffsetOfExprClass: case Expr::PredefinedExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 98b56bcbc7..ee3852a3e9 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1088,6 +1088,14 @@ void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) { OS << ")"; } +void StmtPrinter::VisitConvertVectorExpr(ConvertVectorExpr *Node) { + OS << "__builtin_convertvector("; + PrintExpr(Node->getSrcExpr()); + OS << ", "; + Node->getType().print(OS, Policy); + OS << ")"; +} + void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { if (Node->getSyntacticForm()) { Visit(Node->getSyntacticForm()); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 77c34c41aa..9591127b8a 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -454,6 +454,10 @@ void StmtProfiler::VisitShuffleVectorExpr(const ShuffleVectorExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitConvertVectorExpr(const ConvertVectorExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitChooseExpr(const ChooseExpr *S) { VisitExpr(S); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 287dc6c023..57f102f293 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -257,6 +257,7 @@ public: Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E); + Value *VisitConvertVectorExpr(ConvertVectorExpr *E); Value *VisitMemberExpr(MemberExpr *E); Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { @@ -966,6 +967,81 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { Value *SV = llvm::ConstantVector::get(indices); return Builder.CreateShuffleVector(V1, V2, SV, "shuffle"); } + +Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) { + QualType SrcType = E->getSrcExpr()->getType(), + DstType = E->getType(); + + Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); + + SrcType = CGF.getContext().getCanonicalType(SrcType); + DstType = CGF.getContext().getCanonicalType(DstType); + if (SrcType == DstType) return Src; + + assert(SrcType->isVectorType() && + "ConvertVector source type must be a vector"); + assert(DstType->isVectorType() && + "ConvertVector destination type must be a vector"); + + llvm::Type *SrcTy = Src->getType(); + llvm::Type *DstTy = ConvertType(DstType); + + // Ignore conversions like int -> uint. + if (SrcTy == DstTy) + return Src; + + QualType SrcEltType = SrcType->getAs<VectorType>()->getElementType(), + DstEltType = DstType->getAs<VectorType>()->getElementType(); + + assert(SrcTy->isVectorTy() && + "ConvertVector source IR type must be a vector"); + assert(DstTy->isVectorTy() && + "ConvertVector destination IR type must be a vector"); + + llvm::Type *SrcEltTy = SrcTy->getVectorElementType(), + *DstEltTy = DstTy->getVectorElementType(); + + if (DstEltType->isBooleanType()) { + assert((SrcEltTy->isFloatingPointTy() || + isa<llvm::IntegerType>(SrcEltTy)) && "Unknown boolean conversion"); + + llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy); + if (SrcEltTy->isFloatingPointTy()) { + return Builder.CreateFCmpUNE(Src, Zero, "tobool"); + } else { + return Builder.CreateICmpNE(Src, Zero, "tobool"); + } + } + + // We have the arithmetic types: real int/float. + Value *Res = NULL; + + if (isa<llvm::IntegerType>(SrcEltTy)) { + bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType(); + if (isa<llvm::IntegerType>(DstEltTy)) + Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); + else if (InputSigned) + Res = Builder.CreateSIToFP(Src, DstTy, "conv"); + else + Res = Builder.CreateUIToFP(Src, DstTy, "conv"); + } else if (isa<llvm::IntegerType>(DstEltTy)) { + assert(SrcEltTy->isFloatingPointTy() && "Unknown real conversion"); + if (DstEltType->isSignedIntegerOrEnumerationType()) + Res = Builder.CreateFPToSI(Src, DstTy, "conv"); + else + Res = Builder.CreateFPToUI(Src, DstTy, "conv"); + } else { + assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() && + "Unknown real conversion"); + if (DstEltTy->getTypeID() < SrcEltTy->getTypeID()) + Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); + else + Res = Builder.CreateFPExt(Src, DstTy, "conv"); + } + + return Res; +} + Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { llvm::APSInt Value; if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 07d8ba5a90..bbc7dadde8 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -888,6 +888,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: case tok::kw___builtin_astype: // primary-expression: [OCL] as_type() + case tok::kw___builtin_convertvector: return ParseBuiltinPrimaryExpression(); case tok::kw___null: return Actions.ActOnGNUNullExpr(ConsumeToken()); @@ -1918,6 +1919,34 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { ConsumeParen()); break; } + case tok::kw___builtin_convertvector: { + // The first argument is an expression to be converted, followed by a comma. + ExprResult Expr(ParseAssignmentExpression()); + if (Expr.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", + tok::r_paren)) + return ExprError(); + + // Second argument is the type to bitcast to. + TypeResult DestTy = ParseTypeName(); + if (DestTy.isInvalid()) + return ExprError(); + + // Attempt to consume the r-paren. + if (Tok.isNot(tok::r_paren)) { + Diag(Tok, diag::err_expected_rparen); + SkipUntil(tok::r_paren); + return ExprError(); + } + + Res = Actions.ActOnConvertVectorExpr(Expr.take(), DestTy.get(), StartLoc, + ConsumeParen()); + break; + } } if (Res.isInvalid()) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index cba5ffe5fa..a4fb3cfa45 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1818,6 +1818,37 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getRParenLoc())); } +/// SemaConvertVectorExpr - Handle __builtin_convertvector +ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = TInfo->getType(); + QualType SrcTy = E->getType(); + + if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector) + << E->getSourceRange()); + if (!DstTy->isVectorType() && !DstTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector_type)); + + if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { + unsigned SrcElts = SrcTy->getAs<VectorType>()->getNumElements(); + unsigned DstElts = DstTy->getAs<VectorType>()->getNumElements(); + if (SrcElts != DstElts) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_incompatible_vector) + << E->getSourceRange()); + } + + return Owned(new (Context) ConvertVectorExpr(E, TInfo, DstTy, VK, OK, + BuiltinLoc, RParenLoc)); + +} + /// SemaBuiltinPrefetch - Handle __builtin_prefetch. // This is declared to take (const void*, ...) and can take two // optional constant int args. diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 0d662c8f39..3e8f324027 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -995,6 +995,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::ParenExprClass: case Expr::ParenListExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::VAArgExprClass: return canSubExprsThrow(*this, E); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 10d384b8d8..d68bdbb425 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4463,6 +4463,19 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, RParenLoc)); } +/// ActOnConvertVectorExpr - create a new convert-vector expression from the +/// provided arguments. +/// +/// __builtin_convertvector( value, dst type ) +/// +ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + TypeSourceInfo *TInfo; + GetTypeFromParser(ParsedDestTy, &TInfo); + return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc); +} + /// BuildResolvedCallExpr - Build a call to a resolved expression, /// i.e. an expression not of \p OverloadTy. The expression should /// unary-convert to an expression of function-pointer or diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 008e1eafe4..b91c73b075 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2546,6 +2546,14 @@ public: return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take())); } + /// \brief Build a new convert vector expression. + ExprResult RebuildConvertVectorExpr(SourceLocation BuiltinLoc, + Expr *SrcExpr, TypeSourceInfo *DstTInfo, + SourceLocation RParenLoc) { + return SemaRef.SemaConvertVectorExpr(SrcExpr, DstTInfo, + BuiltinLoc, RParenLoc); + } + /// \brief Build a new template argument pack expansion. /// /// By default, performs semantic analysis to build a new pack expansion @@ -9166,6 +9174,27 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformConvertVectorExpr(ConvertVectorExpr *E) { + ExprResult SrcExpr = getDerived().TransformExpr(E->getSrcExpr()); + if (SrcExpr.isInvalid()) + return ExprError(); + + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo()); + if (!Type) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeSourceInfo() && + SrcExpr.get() == E->getSrcExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildConvertVectorExpr(E->getBuiltinLoc(), + SrcExpr.get(), Type, + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { BlockDecl *oldBlock = E->getBlockDecl(); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 35df252114..23cd9cc726 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -854,6 +854,14 @@ void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { E->setRParenLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) { + VisitExpr(E); + E->BuiltinLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); + E->TInfo = GetTypeSourceInfo(Record, Idx); + E->SrcExpr = Reader.ReadSubExpr(); +} + void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { VisitExpr(E); E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx)); @@ -2104,6 +2112,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ShuffleVectorExpr(Empty); break; + case EXPR_CONVERT_VECTOR: + S = new (Context) ConvertVectorExpr(Empty); + break; + case EXPR_BLOCK: S = new (Context) BlockExpr(Empty); break; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index ee328e2351..d527fcd382 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -794,6 +794,15 @@ void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { Code = serialization::EXPR_SHUFFLE_VECTOR; } +void ASTStmtWriter::VisitConvertVectorExpr(ConvertVectorExpr *E) { + VisitExpr(E); + Writer.AddSourceLocation(E->getBuiltinLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); + Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); + Writer.AddStmt(E->getSrcExpr()); + Code = serialization::EXPR_CONVERT_VECTOR; +} + void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) { VisitExpr(E); Writer.AddDeclRef(E->getBlockDecl(), Record); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 16369f0a2b..52d22edc93 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -726,6 +726,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ParenListExprClass: case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: + case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: case Stmt::CUDAKernelCallExprClass: case Stmt::OpaqueValueExprClass: diff --git a/test/CodeGen/convertvector.c b/test/CodeGen/convertvector.c new file mode 100644 index 0000000000..2b23dd96e1 --- /dev/null +++ b/test/CodeGen/convertvector.c @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -target-cpu corei7-avx -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -target-cpu corei7-avx -emit-llvm -x c++ %s -o - | FileCheck %s + +typedef double vector8double __attribute__((__vector_size__(64))); +typedef float vector8float __attribute__((__vector_size__(32))); +typedef long vector8long __attribute__((__vector_size__(64))); +typedef short vector8short __attribute__((__vector_size__(16))); +typedef unsigned long vector8ulong __attribute__((__vector_size__(64))); +typedef unsigned short vector8ushort __attribute__((__vector_size__(16))); + +#ifdef __cplusplus +#define BOOL bool +#else +#define BOOL _Bool +#endif + +typedef BOOL vector8bool __attribute__((__ext_vector_type__(8))); + +#ifdef __cplusplus +extern "C" { +#endif + +vector8float flt_trunc(vector8double x) { + return __builtin_convertvector(x, vector8float); + // CHECK-LABEL: @flt_trunc + // CHECK: fptrunc <8 x double> %{{[^ ]}} to <8 x float> +} + +vector8double flt_ext(vector8float x) { + return __builtin_convertvector(x, vector8double); + // CHECK-LABEL: @flt_ext + // CHECK: fpext <8 x float> %{{[^ ]}} to <8 x double> +} + +vector8bool flt_tobool(vector8float x) { + return __builtin_convertvector(x, vector8bool); + // CHECK-LABEL: @flt_tobool + // CHECK-NOT: fptoui <8 x float> %{{[^ ]}} to <8 x i1> + // CHECK: fcmp une <8 x float> %{{[^ ]}}, zeroinitializer +} + +vector8long flt_tosi(vector8float x) { + return __builtin_convertvector(x, vector8long); + // CHECK-LABEL: @flt_tosi + // CHECK: fptosi <8 x float> %{{[^ ]}} to <8 x i64> +} + +vector8ulong flt_toui(vector8float x) { + return __builtin_convertvector(x, vector8ulong); + // CHECK-LABEL: @flt_toui + // CHECK: fptoui <8 x float> %{{[^ ]}} to <8 x i64> +} + +vector8ulong fltd_toui(vector8double x) { + return __builtin_convertvector(x, vector8ulong); + // CHECK-LABEL: @fltd_toui + // CHECK: fptoui <8 x double> %{{[^ ]}} to <8 x i64> +} + +vector8ulong int_zext(vector8ushort x) { + return __builtin_convertvector(x, vector8ulong); + // CHECK-LABEL: @int_zext + // CHECK: zext <8 x i16> %{{[^ ]}} to <8 x i64> +} + +vector8long int_sext(vector8short x) { + return __builtin_convertvector(x, vector8long); + // CHECK-LABEL: @int_sext + // CHECK: sext <8 x i16> %{{[^ ]}} to <8 x i64> +} + +vector8bool int_tobool(vector8short x) { + return __builtin_convertvector(x, vector8bool); + // CHECK-LABEL: @int_tobool + // CHECK-NOT: trunc <8 x i16> %{{[^ ]}} to <8 x i1> + // CHECK: icmp ne <8 x i16> %{{[^ ]}}, zeroinitializer +} + +vector8float int_tofp(vector8short x) { + return __builtin_convertvector(x, vector8float); + // CHECK-LABEL: @int_tofp + // CHECK: sitofp <8 x i16> %{{[^ ]}} to <8 x float> +} + +vector8float uint_tofp(vector8ushort x) { + return __builtin_convertvector(x, vector8float); + // CHECK-LABEL: @uint_tofp + // CHECK: uitofp <8 x i16> %{{[^ ]}} to <8 x float> +} + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus +template<typename T> +T int_toT(vector8long x) { + return __builtin_convertvector(x, T); +} + +extern "C" { + vector8double int_toT_fp(vector8long x) { + // CHECK-LABEL: @int_toT_fp + // CHECK: sitofp <8 x i64> %{{[^ ]}} to <8 x double> + return int_toT<vector8double>(x); + } +} +#else +vector8double int_toT_fp(vector8long x) { + return __builtin_convertvector(x, vector8double); +} +#endif + diff --git a/test/PCH/exprs.h b/test/PCH/exprs.h index d08b1f64ed..d6735a727a 100644 --- a/test/PCH/exprs.h +++ b/test/PCH/exprs.h @@ -102,6 +102,10 @@ typedef typeof(__builtin_choose_expr(17 > 19, d0, 1)) choose_expr; // ShuffleVectorExpr typedef typeof(__builtin_shufflevector(vec2, vec2b, 2, 1)) shuffle_expr; +// ConvertVectorExpr +typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef typeof(__builtin_convertvector(vec2, float2)) convert_expr; + // GenericSelectionExpr typedef typeof(_Generic(i, char*: 0, int: 0., default: hello)) generic_selection_expr; diff --git a/test/Preprocessor/feature_tests.c b/test/Preprocessor/feature_tests.c index 19d80468ab..5a2c300e6e 100644 --- a/test/Preprocessor/feature_tests.c +++ b/test/Preprocessor/feature_tests.c @@ -11,6 +11,7 @@ #if !__has_builtin(__builtin_huge_val) || \ !__has_builtin(__builtin_shufflevector) || \ + !__has_builtin(__builtin_convertvector) || \ !__has_builtin(__builtin_trap) || \ !__has_builtin(__c11_atomic_init) || \ !__has_feature(attribute_analyzer_noreturn) || \ diff --git a/test/Sema/convertvector.c b/test/Sema/convertvector.c new file mode 100644 index 0000000000..ccdd87f9e4 --- /dev/null +++ b/test/Sema/convertvector.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef double vector4double __attribute__((__vector_size__(32))); +typedef float vector8float __attribute__((__vector_size__(32))); + +vector8float foo1(vector4double x) { + return __builtin_convertvector(x, vector8float); // expected-error {{same number of elements}} +} + +float foo2(vector4double x) { + return __builtin_convertvector(x, float); // expected-error {{must be a vector type}} +} + +vector8float foo3(double x) { + return __builtin_convertvector(x, vector8float); // expected-error {{must be a vector}} +} + diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index b80ea4ee4f..5aab94403d 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -233,6 +233,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::ParenListExprClass: case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: + case Stmt::ConvertVectorExprClass: case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::VAArgExprClass: diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h index 4d2b3a9840..b8e66d481b 100644 --- a/tools/libclang/RecursiveASTVisitor.h +++ b/tools/libclang/RecursiveASTVisitor.h @@ -2239,6 +2239,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); |