diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 100 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 |
6 files changed, 127 insertions, 10 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 2ac30b4c8cb..45c6a8721f8 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -500,6 +500,7 @@ Expr *Expr::IgnoreParenCasts() { bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { + return true; switch (getStmtClass()) { default: if (Loc) *Loc = getLocStart(); @@ -1363,6 +1364,14 @@ Stmt::child_iterator OverloadExpr::child_end() { return reinterpret_cast<Stmt**>(&SubExprs[NumExprs]); } +// ShuffleVectorExpr +Stmt::child_iterator ShuffleVectorExpr::child_begin() { + return reinterpret_cast<Stmt**>(&SubExprs[0]); +} +Stmt::child_iterator ShuffleVectorExpr::child_end() { + return reinterpret_cast<Stmt**>(&SubExprs[NumExprs]); +} + // VAArgExpr Stmt::child_iterator VAArgExpr::child_begin() { return reinterpret_cast<Stmt**>(&Val); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index bd6d0d44bf2..6e6594c0d8c 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -755,6 +755,15 @@ void StmtPrinter::VisitOverloadExpr(OverloadExpr *Node) { 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) { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 4fb69d045e3..bdd7975fa0c 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -127,6 +127,7 @@ public: Value *VisitObjCMessageExpr(ObjCMessageExpr *E); Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { return EmitLoadOfLValue(E);} Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); + Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E); Value *VisitMemberExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return EmitLoadOfLValue(E); } @@ -449,6 +450,17 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) { return llvm::UndefValue::get(CGF.ConvertType(E->getType())); } +Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { + llvm::SmallVector<llvm::Constant*, 32> indices; + for (unsigned i = 2; i < E->getNumSubExprs(); i++) { + indices.push_back(cast<llvm::Constant>(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.begin(), indices.size()); + return Builder.CreateShuffleVector(V1, V2, SV, "shuffle"); +} + Value *ScalarExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { // Only the lookup mechanism and first two arguments of the method // implementation vary between runtimes. We can get the receiver and diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index e5aab61bb22..9288e020fa7 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -887,10 +887,11 @@ private: //===--------------------------------------------------------------------===// // 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, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6d3eea5e730..bbf43113ee7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -30,7 +30,7 @@ using namespace clang; /// 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 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { 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 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { CheckPrintfArguments(TheCall, HasVAListArg, format_idx); } - return false; + return TheCall; } /// CheckBuiltinCFStringArgument - Checks that the argument to the builtin @@ -200,6 +213,79 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { return false; } +/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. +// 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, + TheCall->getSourceRange()); + + QualType FAType = TheCall->getArg(0)->getType(); + QualType SAType = TheCall->getArg(1)->getType(); + + if (!FAType->isVectorType() || !SAType->isVectorType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector, + SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + delete TheCall; + return true; + } + + if (TheCall->getArg(0)->getType().getCanonicalType().getUnqualifiedType() != + TheCall->getArg(1)->getType().getCanonicalType().getUnqualifiedType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector, + SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + delete TheCall; + return true; + } + + unsigned numElements = FAType->getAsVectorType()->getNumElements(); + if (TheCall->getNumArgs() != numElements+2) { + if (TheCall->getNumArgs() < numElements+2) + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args, + TheCall->getSourceRange()); + else + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_many_args, + TheCall->getSourceRange()); + delete TheCall; + return true; + } + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) { + Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument, + TheCall->getArg(i)->getSourceRange()); + delete TheCall; + return true; + } + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) { + Diag(TheCall->getLocStart(), + diag::err_shufflevector_argument_too_large, + TheCall->getArg(i)->getSourceRange()); + delete TheCall; + return true; + } + } + + llvm::SmallVector<Expr*, 32> exprs; + + for (unsigned i = 0; i < TheCall->getNumArgs(); i++) { + exprs.push_back(TheCall->getArg(i)); + TheCall->setArg(i, 0); + } + + ShuffleVectorExpr* E = new ShuffleVectorExpr( + exprs.begin(), 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. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4567d82719f..64b53d58848 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -723,8 +723,8 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, } // Do special checking on direct calls to functions. - if (FDecl && CheckFunctionCall(FDecl, TheCall.get())) - return true; + if (FDecl) + return CheckFunctionCall(FDecl, TheCall.take()); return TheCall.take(); } |

