Pol Marcet =?utf-8?q?Sardà?= <polmarcetsa...@gmail.com>,
Pol Marcet =?utf-8?q?Sardà?= <polmarcetsa...@gmail.com>,Pol M
 <polmarcetsa...@gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/76...@github.com>


================
@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue &Result, EvalInfo &Info,
+                                   const Expr *E, const QualType &Type) {
+  if (!Evaluate(Result, Info, E))
+    return false;
+
+  if (Result.isLValue()) {
+    // Source of the data is an lvalue; Manually handle the lvalue as if
+    // it was an rvalue to get the current APValue.
+    LValue LValueFound;
+    LValueFound.setFrom(Info.Ctx, Result);
+    if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+      return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo &Info, const FPOptions FPO,
+                                   const Expr *E, QualType SourceTy,
+                                   QualType DestTy, APValue const &Original,
+                                   APValue &Result) {
+  if (SourceTy->isIntegerType()) {
+    if (DestTy->isRealFloatingType()) {
+      Result = APValue(APFloat(0.0));
+      return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+                                  DestTy, Result.getFloat());
+    }
+    if (DestTy->isIntegerType()) {
+      Result = APValue(
+          HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+      return true;
+    }
+  } else if (SourceTy->isRealFloatingType()) {
+    if (DestTy->isRealFloatingType()) {
+      Result = Original;
+      return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+                                    Result.getFloat());
+    }
+    if (DestTy->isIntegerType()) {
+      Result = APValue(APSInt());
+      return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+                                  DestTy, Result.getInt());
+    }
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+    return false;
+
+  QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
+  QualType SourceTy = SourceVecType->castAs<VectorType>()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector<APValue, 4> ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+    APValue Elt;
+    if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+                                Source.getVectorElt(EltNum), Elt))
+      return false;
+    ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
+                                QualType ElemType, APValue const &VecVal1,
+                                APValue const &VecVal2, unsigned EltNum,
+                                APValue &Result) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+    return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+    index = 0;
+
+  if (index >= TotalElementsInAVector)
+    Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+    Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+    return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+    return false;
+
+  VectorType const *DestVecTy = E->getType()->castAs<VectorType>();
+  if (!DestVecTy)
+    return false;
+
+  QualType DestElTy = DestVecTy->getElementType();
+
+  auto TotalElementsInOutputVector = DestVecTy->getNumElements();
+
+  SmallVector<APValue, 4> ResultElements;
+  ResultElements.reserve(TotalElementsInOutputVector);
+  for (unsigned EltNum = 0; EltNum < TotalElementsInOutputVector; ++EltNum) {
----------------
sethp wrote:

Hmm, this looks suspicious to me; it should be OK, but it's not clear on first 
read the link between the number of subexpressions and the output vector 
elements, so it looks like it might be an OOB access.

I think either asserting that `TotalElementsInOutputVector == 
E->getNumSubExprs() - 2`, or using `E->getShuffleMaskIdx(EltNum)` instead of 
`E->getExpr(2 + EltNum)` in `handleVectorShuffle` above would help.

https://github.com/llvm/llvm-project/pull/76615
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to