diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 13a68f3d05f6ae..e61c0a70a0d8aa 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2735,6 +2735,65 @@ bool ByteCodeExprGen::VisitShuffleVectorExpr( return true; } +template +bool ByteCodeExprGen::VisitExtVectorElementExpr( + const ExtVectorElementExpr *E) { + const Expr *Base = E->getBase(); + + SmallVector Indices; + E->getEncodedElementAccess(Indices); + + if (Indices.size() == 1) { + if (!this->visit(Base)) + return false; + + if (E->isGLValue()) { + if (!this->emitConstUint32(Indices[0], E)) + return false; + return this->emitArrayElemPtrPop(PT_Uint32, E); + } + // Else, also load the value. + return this->emitArrayElemPop(classifyPrim(E->getType()), Indices[0], E); + } + + // Create a local variable for the base. + unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true, + /*IsExtended=*/false); + if (!this->visit(Base)) + return false; + if (!this->emitSetLocal(PT_Ptr, BaseOffset, E)) + return false; + + // Now the vector variable for the return value. + if (!Initializing) { + std::optional ResultIndex; + ResultIndex = allocateLocal(E); + if (!ResultIndex) + return false; + if (!this->emitGetPtrLocal(*ResultIndex, E)) + return false; + } + + assert(Indices.size() == E->getType()->getAs()->getNumElements()); + + PrimType ElemT = + classifyPrim(E->getType()->getAs()->getElementType()); + uint32_t DstIndex = 0; + for (uint32_t I : Indices) { + if (!this->emitGetLocal(PT_Ptr, BaseOffset, E)) + return false; + if (!this->emitArrayElemPop(ElemT, I, E)) + return false; + if (!this->emitInitElem(ElemT, DstIndex, E)) + return false; + ++DstIndex; + } + + // Leave the result pointer on the stack. + assert(!DiscardResult); + return true; +} + template bool ByteCodeExprGen::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { if (!E->isExpressibleAsConstantInitializer()) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 7bb5304cac71ef..b0faac8020fb21 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -128,6 +128,7 @@ class ByteCodeExprGen : public ConstStmtVisitor, bool>, bool VisitAddrLabelExpr(const AddrLabelExpr *E); bool VisitConvertVectorExpr(const ConvertVectorExpr *E); bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); + bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); protected: diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp index 1e0d473cbca5a9..61c400b57b3f87 100644 --- a/clang/test/AST/Interp/vectors.cpp +++ b/clang/test/AST/Interp/vectors.cpp @@ -70,3 +70,14 @@ namespace BoolToSignedIntegralCast{ static_assert(intsT[2] == -1, "");// ref-error {{not an integral constant expression}} static_assert(intsT[3] == -1, "");// ref-error {{not an integral constant expression}} } + +namespace VectorElementExpr { + typedef int int2 __attribute__((ext_vector_type(2))); + typedef int int4 __attribute__((ext_vector_type(4))); + constexpr int oneElt = int4(3).x; + static_assert(oneElt == 3); + + constexpr int2 twoElts = ((int4){11, 22, 33, 44}).yz; + static_assert(twoElts.x == 22, ""); // ref-error {{not an integral constant expression}} + static_assert(twoElts.y == 33, ""); // ref-error {{not an integral constant expression}} +} diff --git a/clang/test/CodeGenOpenCLCXX/constexpr.clcpp b/clang/test/CodeGenOpenCLCXX/constexpr.clcpp index 0576418c944baf..5de7106fe54179 100644 --- a/clang/test/CodeGenOpenCLCXX/constexpr.clcpp +++ b/clang/test/CodeGenOpenCLCXX/constexpr.clcpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - -fexperimental-new-constant-interpreter | FileCheck %s typedef int int2 __attribute__((ext_vector_type(2))); typedef int int4 __attribute__((ext_vector_type(4)));