summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-01-03 23:24:20 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-01-03 23:24:20 +0000
commitb9c71290123cf7d4be45d7456d9f1e02b3aa0ab5 (patch)
treee744639c46b6723bea62b42f38239c5f09efad83 /clang/lib
parent6ca97df95114dab32bcddc967aea6cf0473aca70 (diff)
downloadbcm5719-llvm-b9c71290123cf7d4be45d7456d9f1e02b3aa0ab5.tar.gz
bcm5719-llvm-b9c71290123cf7d4be45d7456d9f1e02b3aa0ab5.zip
Support constant evaluation for OpenCL nested vector literals. Patch by Anton Lokhmotov.
llvm-svn: 147496
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ExprConstant.cpp75
1 files changed, 32 insertions, 43 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3579e75d945..9ac311ae58e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3181,53 +3181,42 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
QualType EltTy = VT->getElementType();
SmallVector<APValue, 4> Elements;
- // If a vector is initialized with a single element, that value
- // becomes every element of the vector, not just the first.
- // This is the behavior described in the IBM AltiVec documentation.
- if (NumInits == 1) {
-
- // Handle the case where the vector is initialized by another
- // vector (OpenCL 6.1.6).
- if (E->getInit(0)->getType()->isVectorType())
- return Visit(E->getInit(0));
-
- APValue InitValue;
- if (EltTy->isIntegerType()) {
+ // The number of initializers can be less than the number of
+ // vector elements. For OpenCL, this can be due to nested vector
+ // initialization. For GCC compatibility, missing trailing elements
+ // should be initialized with zeroes.
+ unsigned CountInits = 0, CountElts = 0;
+ while (CountElts < NumElements) {
+ // Handle nested vector initialization.
+ if (CountInits < NumInits
+ && E->getInit(CountInits)->getType()->isExtVectorType()) {
+ APValue v;
+ if (!EvaluateVector(E->getInit(CountInits), v, Info))
+ return Error(E);
+ unsigned vlen = v.getVectorLength();
+ for (unsigned j = 0; j < vlen; j++)
+ Elements.push_back(v.getVectorElt(j));
+ CountElts += vlen;
+ } else if (EltTy->isIntegerType()) {
llvm::APSInt sInt(32);
- if (!EvaluateInteger(E->getInit(0), sInt, Info))
- return false;
- InitValue = APValue(sInt);
+ if (CountInits < NumInits) {
+ if (!EvaluateInteger(E->getInit(CountInits), sInt, Info))
+ return Error(E);
+ } else // trailing integer zero.
+ sInt = Info.Ctx.MakeIntValue(0, EltTy);
+ Elements.push_back(APValue(sInt));
+ CountElts++;
} else {
llvm::APFloat f(0.0);
- if (!EvaluateFloat(E->getInit(0), f, Info))
- return false;
- InitValue = APValue(f);
- }
- for (unsigned i = 0; i < NumElements; i++) {
- Elements.push_back(InitValue);
- }
- } else {
- for (unsigned i = 0; i < NumElements; i++) {
- if (EltTy->isIntegerType()) {
- llvm::APSInt sInt(32);
- if (i < NumInits) {
- if (!EvaluateInteger(E->getInit(i), sInt, Info))
- return false;
- } else {
- sInt = Info.Ctx.MakeIntValue(0, EltTy);
- }
- Elements.push_back(APValue(sInt));
- } else {
- llvm::APFloat f(0.0);
- if (i < NumInits) {
- if (!EvaluateFloat(E->getInit(i), f, Info))
- return false;
- } else {
- f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
- }
- Elements.push_back(APValue(f));
- }
+ if (CountInits < NumInits) {
+ if (!EvaluateFloat(E->getInit(CountInits), f, Info))
+ return Error(E);
+ } else // trailing float zero.
+ f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
+ Elements.push_back(APValue(f));
+ CountElts++;
}
+ CountInits++;
}
return Success(Elements, E);
}
OpenPOWER on IntegriCloud