diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2008-05-14 19:38:39 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2008-05-14 19:38:39 +0000 |
commit | d38617c8a50f9729c254ab76cd359af797c6739b (patch) | |
tree | 2b2fbbd20b59bc7972a339b79e420ecdc30834e0 /lib/Sema/SemaChecking.cpp | |
parent | 9d7405fafd5bc08d38bc75579927bf414570bd61 (diff) |
Implementation of __builtin_shufflevector, a portable builtin capable of
expressing the full flexibility of the LLVM shufflevector instruction.
The expected immediate usage is in *mmintrin.h, so that they don't
depend on the mess of gcc-inherited (and not completely implemented)
shuffle builtins.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51113 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 100 |
1 files changed, 93 insertions, 7 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6d3eea5e73..bbf43113ee 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/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. |