]> granicus.if.org Git - clang/commitdiff
Implement Eli's feedback for vecto constant expressions;
authorNate Begeman <natebegeman@mac.com>
Wed, 1 Jul 2009 07:50:47 +0000 (07:50 +0000)
committerNate Begeman <natebegeman@mac.com>
Wed, 1 Jul 2009 07:50:47 +0000 (07:50 +0000)
For ExtVectorType, initializer is splatted to all elements.
For VectorType, initializer is bitcast to vector type.

Verified that for VectorType, output is identical to gcc.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74600 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp

index 4a9c420cb9c29446ff0de3fe716d9281e09dd787..ec2005a99fc95d1e021f31774239fc456f710d4d 100644 (file)
@@ -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