aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp57
1 files changed, 52 insertions, 5 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 4a9c420cb9..ec2005a99f 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -485,6 +485,11 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
}
APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
+ const VectorType *VTy = E->getType()->getAsVectorType();
+ QualType EltTy = VTy->getElementType();
+ unsigned NElts = VTy->getNumElements();
+ unsigned EltWidth = Info.Ctx.getTypeSize(EltTy);
+
const Expr* SE = E->getSubExpr();
QualType SETy = SE->getType();
APValue Result = APValue();
@@ -501,13 +506,55 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
if (EvaluateFloat(SE, F, Info))
Result = APValue(F);
}
+
+ if (!Result.isInt() && Result.isFloat())
+ return APValue();
+
+ // For casts of a scalar to ExtVector, convert the scalar to the element type
+ // and splat it to all elements.
+ if (E->getType()->isExtVectorType()) {
+ if (EltTy->isIntegerType() && Result.isInt())
+ Result = APValue(HandleIntToIntCast(EltTy, SETy, Result.getInt(),
+ Info.Ctx));
+ else if (EltTy->isIntegerType())
+ Result = APValue(HandleFloatToIntCast(EltTy, SETy, Result.getFloat(),
+ Info.Ctx));
+ else if (EltTy->isRealFloatingType() && Result.isInt())
+ Result = APValue(HandleIntToFloatCast(EltTy, SETy, Result.getInt(),
+ Info.Ctx));
+ else if (EltTy->isRealFloatingType())
+ Result = APValue(HandleFloatToFloatCast(EltTy, SETy, Result.getFloat(),
+ Info.Ctx));
+ else
+ return APValue();
- if (Result.isInt() || Result.isFloat()) {
- unsigned NumElts = E->getType()->getAsVectorType()->getNumElements();
- llvm::SmallVector<APValue, 4> Elts(NumElts, Result);
- Result = APValue(&Elts[0], Elts.size());
+ // Splat and create vector APValue.
+ llvm::SmallVector<APValue, 4> Elts(NElts, Result);
+ return APValue(&Elts[0], Elts.size());
}
- return Result;
+
+ // For casts of a scalar to regular gcc-style vector type, bitcast the scalar
+ // to the vector. To construct the APValue vector initializer, bitcast the
+ // initializing value to an APInt, and shift out the bits pertaining to each
+ // element.
+ APSInt Init;
+ Init = Result.isInt() ? Result.getInt() : Result.getFloat().bitcastToAPInt();
+
+ llvm::SmallVector<APValue, 4> Elts;
+ for (unsigned i = 0; i != NElts; ++i) {
+ APSInt Tmp = Init;
+ Tmp.extOrTrunc(EltWidth);
+
+ if (EltTy->isIntegerType())
+ Elts.push_back(APValue(Tmp));
+ else if (EltTy->isRealFloatingType())
+ Elts.push_back(APValue(APFloat(Tmp)));
+ else
+ return APValue();
+
+ Init >>= EltWidth;
+ }
+ return APValue(&Elts[0], Elts.size());
}
APValue