diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-03 23:24:20 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-03 23:24:20 +0000 |
commit | 3edd5a99332dd8ec94a545476dc3c9ed50dec78f (patch) | |
tree | 421a1d53e4cbc5f5bb40e2c71ecc960ec3f385e5 /lib/AST/ExprConstant.cpp | |
parent | de9f25365ca1fbc146eefeb839053b1cf9b75ae1 (diff) |
Support constant evaluation for OpenCL nested vector literals. Patch by Anton Lokhmotov.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 75 |
1 files changed, 32 insertions, 43 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 3579e75d94..9ac311ae58 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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); } |