Skip to content

Commit 7505452

Browse files
committed
[clang][Interp] Implement VectorSplat casts
1 parent 8cd8ebe commit 7505452

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,35 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
398398
return true;
399399
}
400400

401+
case CK_VectorSplat: {
402+
assert(!classify(CE->getType()));
403+
assert(classify(SubExpr->getType()));
404+
assert(CE->getType()->isVectorType());
405+
406+
if (DiscardResult)
407+
return this->discard(SubExpr);
408+
409+
assert(Initializing); // FIXME: Not always correct.
410+
const auto *VT = CE->getType()->getAs<VectorType>();
411+
PrimType ElemT = classifyPrim(SubExpr);
412+
unsigned ElemOffset = allocateLocalPrimitive(
413+
SubExpr, ElemT, /*IsConst=*/true, /*IsExtended=*/false);
414+
415+
if (!this->visit(SubExpr))
416+
return false;
417+
if (!this->emitSetLocal(ElemT, ElemOffset, CE))
418+
return false;
419+
420+
for (unsigned I = 0; I != VT->getNumElements(); ++I) {
421+
if (!this->emitGetLocal(ElemT, ElemOffset, CE))
422+
return false;
423+
if (!this->emitInitElem(ElemT, I, CE))
424+
return false;
425+
}
426+
427+
return true;
428+
}
429+
401430
case CK_ToVoid:
402431
return discard(SubExpr);
403432

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,20 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
148148
return Ctx.classify(Ty);
149149
}
150150

151-
/// Classifies a known primitive type
151+
/// Classifies a known primitive type.
152152
PrimType classifyPrim(QualType Ty) const {
153153
if (auto T = classify(Ty)) {
154154
return *T;
155155
}
156156
llvm_unreachable("not a primitive type");
157157
}
158+
/// Classifies a known primitive expression.
159+
PrimType classifyPrim(const Expr *E) const {
160+
if (auto T = classify(E))
161+
return *T;
162+
llvm_unreachable("not a primitive type");
163+
}
164+
158165
/// Evaluates an expression and places the result on the stack. If the
159166
/// expression is of composite type, a local variable will be created
160167
/// and a pointer to said variable will be placed on the stack.

clang/test/AST/Interp/vectors.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
22
// RUN: %clang_cc1 -verify=ref,both %s
33

4-
// ref-no-diagnostics
5-
64
typedef int __attribute__((vector_size(16))) VI4;
75
constexpr VI4 A = {1,2,3,4};
6+
static_assert(A[0] == 1, ""); // ref-error {{not an integral constant expression}}
7+
static_assert(A[1] == 2, ""); // ref-error {{not an integral constant expression}}
8+
static_assert(A[2] == 3, ""); // ref-error {{not an integral constant expression}}
9+
static_assert(A[3] == 4, ""); // ref-error {{not an integral constant expression}}
10+
11+
/// VectorSplat casts
12+
typedef __attribute__(( ext_vector_type(4) )) float float4;
13+
constexpr float4 vec4_0 = (float4)0.5f;
14+
static_assert(vec4_0[0] == 0.5, ""); // ref-error {{not an integral constant expression}}
15+
static_assert(vec4_0[1] == 0.5, ""); // ref-error {{not an integral constant expression}}
16+
static_assert(vec4_0[2] == 0.5, ""); // ref-error {{not an integral constant expression}}
17+
static_assert(vec4_0[3] == 0.5, ""); // ref-error {{not an integral constant expression}}
18+
constexpr int vec4_0_discarded = ((float4)12.0f, 0);
19+
20+
821

922
/// From constant-expression-cxx11.cpp
1023
namespace Vector {

0 commit comments

Comments
 (0)