[cfe-commits] r51113 - in /cfe/trunk: include/clang/AST/Builtins.def include/clang/AST/Expr.h include/clang/AST/StmtNodes.def include/clang/Basic/DiagnosticKinds.def lib/AST/Expr.cpp lib/AST/StmtPrinter.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/Sema.h lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp test/CodeGen/builtinshufflevector.c
Eli Friedman
eli.friedman at gmail.com
Wed May 14 12:38:40 PDT 2008
Author: efriedma
Date: Wed May 14 14:38:39 2008
New Revision: 51113
URL: http://llvm.org/viewvc/llvm-project?rev=51113&view=rev
Log:
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.
Added:
cfe/trunk/test/CodeGen/builtinshufflevector.c
Modified:
cfe/trunk/include/clang/AST/Builtins.def
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/StmtNodes.def
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/include/clang/AST/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.def?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.def (original)
+++ cfe/trunk/include/clang/AST/Builtins.def Wed May 14 14:38:39 2008
@@ -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")
// Atomic operators builtin.
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed May 14 14:38:39 2008
@@ -1095,6 +1095,75 @@
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), NumExprs(nexpr)
+ {
+ SubExprs = new Expr*[nexpr];
+ for (unsigned i = 0; i < nexpr; i++)
+ SubExprs[i] = args[i];
+ }
+
+ 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() {
+ for (unsigned i = 0; i < NumExprs; i++)
+ delete SubExprs[i];
+ 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];
+ }
+ const Expr *getExpr(unsigned Index) const {
+ assert((Index < NumExprs) && "Arg access out of range!");
+ return SubExprs[Index];
+ }
+
+ int getShuffleMaskIdx(ASTContext &Ctx, unsigned N) {
+ llvm::APSInt Result(32);
+ bool result = getExpr(N+2)->isIntegerConstantExpr(Result, Ctx);
+ assert(result && "Must be integer constant");
+ return Result.getZExtValue();
+ }
+
+ // 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:
Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Wed May 14 14:38:39 2008
@@ -103,8 +103,9 @@
// Clang Extensions.
STMT(76, OverloadExpr , Expr)
+STMT(77, ShuffleVectorExpr , Expr)
-LAST_EXPR(76)
+LAST_EXPR(77)
#undef STMT
#undef FIRST_STMT
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed May 14 14:38:39 2008
@@ -1056,4 +1056,13 @@
DIAG(ext_return_has_expr, EXTENSION,
"void function '%0' should not return a value")
+DIAG(err_shufflevector_non_vector, ERROR,
+ "first two arguments to __builtin_shufflevector must be vectors")
+DIAG(err_shufflevector_incompatible_vector, ERROR,
+ "first two arguments to __builtin_shufflevector must have the same type")
+DIAG(err_shufflevector_nonconstant_argument, ERROR,
+ "indexes for __builtin_shufflevector must be constant integers")
+DIAG(err_shufflevector_argument_too_large, ERROR,
+ "indexes for __builtin_shufflevector must be less than the total number of vector elements")
+
#undef DIAG
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed May 14 14:38:39 2008
@@ -500,6 +500,7 @@
bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
+ return true;
switch (getStmtClass()) {
default:
if (Loc) *Loc = getLocStart();
@@ -1363,6 +1364,14 @@
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);
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed May 14 14:38:39 2008
@@ -755,6 +755,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) {
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed May 14 14:38:39 2008
@@ -127,6 +127,7 @@
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 @@
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
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed May 14 14:38:39 2008
@@ -887,10 +887,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,
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed May 14 14:38:39 2008
@@ -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,6 +213,79 @@
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.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=51113&r1=51112&r2=51113&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed May 14 14:38:39 2008
@@ -723,8 +723,8 @@
}
// 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();
}
Added: cfe/trunk/test/CodeGen/builtinshufflevector.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtinshufflevector.c?rev=51113&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/builtinshufflevector.c (added)
+++ cfe/trunk/test/CodeGen/builtinshufflevector.c Wed May 14 14:38:39 2008
@@ -0,0 +1,5 @@
+// RUN: clang -emit-llvm < %s 2>&1 | grep 'shufflevector' | count 1
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a(v4si x, v4si y) {return __builtin_shufflevector(x, y, 3, 2, 5, 7);}
+
More information about the cfe-commits
mailing list