Index: include/clang/AST/Builtins.def =================================================================== --- include/clang/AST/Builtins.def (revision 47702) +++ include/clang/AST/Builtins.def (working copy) @@ -96,6 +96,8 @@ BUILTIN(__builtin_memcpy, "v*v*vC*z", "n") BUILTIN(__builtin_expect, "iii" , "nc") +BUILTIN(__builtin_shufflevector, "v." , "nc") + BUILTIN(__builtin_alloca, "v*z" , "n") #undef BUILTIN Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h (revision 47702) +++ include/clang/AST/Expr.h (working copy) @@ -1099,6 +1099,57 @@ virtual child_iterator child_end(); }; +/// ShuffleVectorExpr - clang-specific builtin-in function +/// __builtin_shufflevector. +/// This AST node represents a operator that does a constant +/// shuffle, similar to LLVM's shufflevector instruction. It takes +/// two vectors and a variable number of constant indices, +/// and returns the appropriately shuffled vector. +class ShuffleVectorExpr : public Expr { + SourceLocation BuiltinLoc, RParenLoc; + + // SubExprs - the list of values passed to the __builtin_shufflevector + // function. The first two are vectors, and the rest are constant + // indices. The number of values in this list is always + // 2+the number of indices in the vector type. + Expr **SubExprs; + unsigned NumExprs; + +public: + ShuffleVectorExpr(Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) : + Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc), + RParenLoc(RP), SubExprs(args), NumExprs(nexpr) {} + + virtual SourceRange getSourceRange() const { + return SourceRange(BuiltinLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ShuffleVectorExprClass; + } + static bool classof(const ShuffleVectorExpr *) { return true; } + + ~ShuffleVectorExpr() { + delete [] SubExprs; + } + + /// getNumSubExprs - Return the size of the SubExprs array. This includes the + /// constant expression, the actual arguments passed in, and the function + /// pointers. + unsigned getNumSubExprs() const { return NumExprs; } + + /// getExpr - Return the Expr at the specified index. + Expr *getExpr(unsigned Index) { + assert((Index < NumExprs) && "Arg access out of range!"); + return SubExprs[Index]; + } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. /// This AST node is similar to the conditional operator (?:) in C, with /// the following exceptions: Index: include/clang/AST/StmtNodes.def =================================================================== --- include/clang/AST/StmtNodes.def (revision 47702) +++ include/clang/AST/StmtNodes.def (working copy) @@ -102,8 +102,9 @@ // Clang Extensions. STMT(76, OverloadExpr , Expr) +STMT(77, ShuffleVectorExpr , Expr) -LAST_EXPR(76) +LAST_EXPR(77) #undef STMT #undef FIRST_STMT Index: Sema/SemaChecking.cpp =================================================================== --- Sema/SemaChecking.cpp (revision 47702) +++ Sema/SemaChecking.cpp (working copy) @@ -30,7 +30,7 @@ /// CheckFunctionCall - Check a direct function call for various correctness /// and safety properties not strictly enforced by the C type system. -bool +Action::ExprResult Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { // Get the IdentifierInfo* for the called function. @@ -40,23 +40,36 @@ case Builtin::BI__builtin___CFStringMakeConstantString: assert(TheCall->getNumArgs() == 1 && "Wrong # arguments to builtin CFStringMakeConstantString"); - return CheckBuiltinCFStringArgument(TheCall->getArg(0)); + if (!CheckBuiltinCFStringArgument(TheCall->getArg(0))) { + delete TheCall; + return true; + } + return TheCall; case Builtin::BI__builtin_va_start: - return SemaBuiltinVAStart(TheCall); - + if (!SemaBuiltinVAStart(TheCall)) { + delete TheCall; + return true; + } + return TheCall; case Builtin::BI__builtin_isgreater: case Builtin::BI__builtin_isgreaterequal: case Builtin::BI__builtin_isless: case Builtin::BI__builtin_islessequal: case Builtin::BI__builtin_islessgreater: case Builtin::BI__builtin_isunordered: - return SemaBuiltinUnorderedCompare(TheCall); + if (!SemaBuiltinUnorderedCompare(TheCall)) { + delete TheCall; + return true; + } + return TheCall; + case Builtin::BI__builtin_shufflevector: + return SemaBuiltinShuffleVector(TheCall); } // Search the KnownFunctionIDs for the identifier. unsigned i = 0, e = id_num_known_functions; for (; i != e; ++i) { if (KnownFunctionIDs[i] == FnInfo) break; } - if (i == e) return false; + if (i == e) return TheCall; // Printf checking. if (i <= id_vprintf) { @@ -82,7 +95,7 @@ CheckPrintfArguments(TheCall, HasVAListArg, format_idx); } - return false; + return TheCall; } /// CheckBuiltinCFStringArgument - Checks that the argument to the builtin @@ -200,7 +213,56 @@ return false; } +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and +/// friends. This is declared to take (...), so we have to check everything. +Action::ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 3) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + QualType FAType = TheCall->getArg(0)->getType(); + QualType SAType = TheCall->getArg(1)->getType(); + unsigned numElements; + if (const VectorType* VType = FAType->getAsVectorType()) { + numElements = VType->getNumElements(); + } else if (const OCUVectorType* VType = FAType->getAsOCUVectorType()) { + numElements = VType->getNumElements(); + } else { + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + } + + if (!Context.typesAreCompatible( + TheCall->getArg(0)->getType().getUnqualifiedType(), + TheCall->getArg(1)->getType().getUnqualifiedType())) { + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + } + + if (numElements+2 != TheCall->getNumArgs()) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + if (Result >= llvm::APSInt(llvm::APInt(32, numElements*2), false)) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args); + } + + Expr** exprs = new Expr*[TheCall->getNumArgs()]; + + for (unsigned i = 0; i < TheCall->getNumArgs(); i++) { + exprs[i] = TheCall->getArg(i); + TheCall->setArg(i, 0); + } + + ShuffleVectorExpr* E = new ShuffleVectorExpr(exprs, numElements+2, FAType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc()); + + delete TheCall; + + return E; +} + /// CheckPrintfArguments - Check calls to printf (and similar functions) for /// correct use of format strings. /// Index: Sema/SemaExpr.cpp =================================================================== --- Sema/SemaExpr.cpp (revision 47702) +++ Sema/SemaExpr.cpp (working copy) @@ -668,8 +668,7 @@ if (ImplicitCastExpr *IcExpr = dyn_cast(Fn)) if (DeclRefExpr *DRExpr = dyn_cast(IcExpr->getSubExpr())) if (FunctionDecl *FDecl = dyn_cast(DRExpr->getDecl())) - if (CheckFunctionCall(FDecl, TheCall.get())) - return true; + return CheckFunctionCall(FDecl, TheCall.take()); return TheCall.take(); } Index: Sema/Sema.h =================================================================== --- Sema/Sema.h (revision 47702) +++ Sema/Sema.h (working copy) @@ -796,10 +796,11 @@ //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system private: - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); + Action::ExprResult CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); bool CheckBuiltinCFStringArgument(Expr* Arg); bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); + Action::ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); void CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg, unsigned format_idx); void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, Index: AST/Expr.cpp =================================================================== --- AST/Expr.cpp (revision 47702) +++ AST/Expr.cpp (working copy) @@ -1357,6 +1357,14 @@ return reinterpret_cast(&SubExprs[NumExprs]); } +// ShuffleVectorExpr +Stmt::child_iterator ShuffleVectorExpr::child_begin() { + return reinterpret_cast(&SubExprs[0]); +} +Stmt::child_iterator ShuffleVectorExpr::child_end() { + return reinterpret_cast(&SubExprs[NumExprs]); +} + // VAArgExpr Stmt::child_iterator VAArgExpr::child_begin() { return reinterpret_cast(&Val); Index: AST/StmtPrinter.cpp =================================================================== --- AST/StmtPrinter.cpp (revision 47702) +++ AST/StmtPrinter.cpp (working copy) @@ -750,6 +750,15 @@ OS << ")"; } +void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) { + OS << "__builtin_shufflevector("; + for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) { + if (i) OS << ", "; + PrintExpr(Node->getExpr(i)); + } + OS << ")"; +} + void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { OS << "{ "; for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) { Index: CodeGen/CGExprScalar.cpp =================================================================== --- CodeGen/CGExprScalar.cpp (revision 47702) +++ CodeGen/CGExprScalar.cpp (working copy) @@ -121,6 +121,7 @@ return EmitLoadOfLValue(E); } Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); + Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E); Value *VisitMemberExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitOCUVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitStringLiteral(Expr *E) { return EmitLValue(E).getAddress(); } @@ -443,6 +444,17 @@ return llvm::UndefValue::get(CGF.ConvertType(E->getType())); } +Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { + std::vector indices; + for (unsigned i = 2; i < E->getNumSubExprs(); i++) { + indices.push_back(cast(CGF.EmitScalarExpr(E->getExpr(i)))); + } + Value* V1 = CGF.EmitScalarExpr(E->getExpr(0)); + Value* V2 = CGF.EmitScalarExpr(E->getExpr(1)); + Value* SV = llvm::ConstantVector::get(indices); + return Builder.CreateShuffleVector(V1, V2, SV, "shuffle"); +} + Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { // Emit subscript expressions in rvalue context's. For most cases, this just // loads the lvalue formed by the subscript expr. However, we have to be