Support evaluation of vector constant expressions, and codegen of same.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62455 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index b5a234c..f45bd78 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -318,6 +318,78 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Vector Evaluation
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class VISIBILITY_HIDDEN VectorExprEvaluator
+  : public StmtVisitor<VectorExprEvaluator, APValue> {
+    EvalInfo &Info;
+  public:
+    
+    VectorExprEvaluator(EvalInfo &info) : Info(info) {}
+    
+    APValue VisitStmt(Stmt *S) {
+      return APValue();
+    }
+    
+    APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+    APValue VisitCastExpr(const CastExpr* E);
+    APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
+    APValue VisitInitListExpr(const InitListExpr *E);
+  };
+} // end anonymous namespace
+
+static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
+  if (!E->getType()->isVectorType())
+    return false;
+  Result = VectorExprEvaluator(Info).Visit(const_cast<Expr*>(E));
+  return !Result.isUninit();
+}
+
+APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
+  const Expr* SE = E->getSubExpr();
+
+  // Check for vector->vector bitcast.
+  if (SE->getType()->isVectorType())
+    return this->Visit(const_cast<Expr*>(SE));
+
+  return APValue();
+}
+
+APValue 
+VectorExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+  return this->Visit(const_cast<Expr*>(E->getInitializer()));
+}
+
+APValue 
+VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
+  const VectorType *VT = E->getType()->getAsVectorType();
+  unsigned NumInits = E->getNumInits();
+
+  if (!VT || VT->getNumElements() != NumInits)
+    return APValue();
+  
+  QualType EltTy = VT->getElementType();
+  llvm::SmallVector<APValue, 4> Elements;
+
+  for (unsigned i = 0; i < NumInits; i++) {
+    if (EltTy->isIntegerType()) {
+      llvm::APSInt sInt(32);
+      if (!EvaluateInteger(E->getInit(i), sInt, Info))
+        return APValue();
+      Elements.push_back(APValue(sInt));
+    } else {
+      llvm::APFloat f(0.0);
+      if (!EvaluateFloat(E->getInit(i), f, Info))
+        return APValue();
+      Elements.push_back(APValue(f));
+    }
+  }
+  return APValue(&Elements[0], Elements.size());
+}
+
+//===----------------------------------------------------------------------===//
 // Integer Evaluation
 //===----------------------------------------------------------------------===//
 
@@ -1067,6 +1139,7 @@
 
 bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
   Expr* SubExpr = E->getSubExpr();
+  
   const llvm::fltSemantics& destSemantics =
       Info.Ctx.getFloatTypeSemantics(E->getType());
   if (SubExpr->getType()->isIntegralType()) {
@@ -1189,7 +1262,10 @@
 bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
   EvalInfo Info(Ctx, Result);
 
-  if (getType()->isIntegerType()) {
+  if (getType()->isVectorType()) {
+    if (!EvaluateVector(this, Result.Val, Info))
+      return false;
+  } else if (getType()->isIntegerType()) {
     llvm::APSInt sInt(32);
     if (!EvaluateInteger(this, sInt, Info))
       return false;