From 161f09abd7df2c92f994bb0e41f4fde14b235c7e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 6 Dec 2011 22:44:34 +0000 Subject: [PATCH] Move vector bitcast handling in constant expressions from the expression evaluator into constant initializer handling / IRGen. The practical consequence of this is that the bitcast now lives in the constant's definition, rather than in its uses. The code in the constant expression evaluator was producing vectors of the wrong type and size (and possibly of the wrong value for a big-endian int-to-vector bitcast). We were getting away with this only because we don't yet support constant-folding of any expressions which inspect vector values. llvm-svn: 145981 --- clang/lib/AST/Expr.cpp | 22 +++++++++++++--------- clang/lib/AST/ExprConstant.cpp | 32 +------------------------------- clang/test/CodeGen/altivec.c | 9 +++++++++ 3 files changed, 23 insertions(+), 40 deletions(-) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index c2880a0ad138..08611c32c692 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2541,23 +2541,27 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: case ImplicitCastExprClass: - case CStyleCastExprClass: + case CStyleCastExprClass: { + const CastExpr *CE = cast(this); + + // Handle bitcasts of vector constants. + if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + // Handle casts with a destination that's a struct or union; this // deals with both the gcc no-op struct cast extension and the // cast-to-union extension. if (getType()->isRecordType()) - return cast(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + // Integer->integer casts can be handled here, which is important for // things like (int)(&&x-&&y). Scary but true. if (getType()->isIntegerType() && - cast(this)->getSubExpr()->getType()->isIntegerType()) - return cast(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - + CE->getSubExpr()->getType()->isIntegerType()) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + break; - + } case MaterializeTemporaryExprClass: return cast(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 438bef5de876..6a290a6c8340 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2502,11 +2502,9 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { const VectorType *VTy = E->getType()->castAs(); - QualType EltTy = VTy->getElementType(); unsigned NElts = VTy->getNumElements(); - unsigned EltWidth = Info.Ctx.getTypeSize(EltTy); - const Expr* SE = E->getSubExpr(); + const Expr *SE = E->getSubExpr(); QualType SETy = SE->getType(); switch (E->getCastKind()) { @@ -2530,34 +2528,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { SmallVector Elts(NElts, Val); return Success(Elts, E); } - case CK_BitCast: { - // FIXME: this is wrong for any cast other than a no-op cast. - if (SETy->isVectorType()) - return Visit(SE); - - if (!SETy->isIntegerType()) - return Error(E); - - APSInt Init; - if (!EvaluateInteger(SE, Init, Info)) - return Error(E); - - assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && - "Vectors must be composed of ints or floats"); - - SmallVector Elts; - for (unsigned i = 0; i != NElts; ++i) { - APSInt Tmp = Init.extOrTrunc(EltWidth); - - if (EltTy->isIntegerType()) - Elts.push_back(APValue(Tmp)); - else - Elts.push_back(APValue(APFloat(Tmp))); - - Init >>= EltWidth; - } - return Success(Elts, E); - } default: return ExprEvaluatorBaseTy::VisitCastExpr(E); } diff --git a/clang/test/CodeGen/altivec.c b/clang/test/CodeGen/altivec.c index c3b1f42e06d8..bd694a6a56de 100644 --- a/clang/test/CodeGen/altivec.c +++ b/clang/test/CodeGen/altivec.c @@ -5,6 +5,15 @@ vector int test0 = (vector int)(1); // CHECK: @test0 = global <4 x i32> vector float test1 = (vector float)(1.0); // CHECK: @test1 = global <4 x float> +// CHECK: @v1 = global <16 x i8> bitcast (<4 x i32> to <16 x i8>) +vector char v1 = (vector char)((vector int)(1, 2, 3, 4)); +// CHECK: @v2 = global <16 x i8> bitcast (<4 x float> to <16 x i8>) +vector char v2 = (vector char)((vector float)(1.0f, 2.0f, 3.0f, 4.0f)); +// CHECK: @v3 = global <16 x i8> bitcast (<4 x i32> to <16 x i8>) +vector char v3 = (vector char)((vector int)('a', 'b', 'c', 'd')); +// CHECK: @v4 = global <4 x i32> bitcast (<16 x i8> to <4 x i32>) +vector int v4 = (vector char){1, 2, 3, 4}; + void test2() { vector int vi;