Skip to content

Commit 1ee924c

Browse files
committed
[clang][ExprConst] Reject unary vector shuffles
This is not implemented at compile time and asserts later in codegen, so reject it here.
1 parent 24b5867 commit 1ee924c

File tree

4 files changed

+42
-21
lines changed

4 files changed

+42
-21
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3986,6 +3986,10 @@ bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
39863986

39873987
template <class Emitter>
39883988
bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
3989+
// FIXME: Unary shuffle with mask not currently supported.
3990+
if (E->getNumSubExprs() == 2)
3991+
return this->emitInvalid(E);
3992+
39893993
assert(Initializing);
39903994
assert(E->getNumSubExprs() > 2);
39913995

clang/lib/AST/ExprConstant.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12160,6 +12160,9 @@ static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
1216012160
}
1216112161

1216212162
bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
12163+
// FIXME: Unary shuffle with mask not currently supported.
12164+
if (E->getNumSubExprs() == 2)
12165+
return Error(E);
1216312166
APValue VecVal1;
1216412167
const Expr *Vec1 = E->getExpr(0);
1216512168
if (!EvaluateAsRValue(Info, Vec1, VecVal1))

clang/lib/Sema/SemaChecking.cpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5558,7 +5558,8 @@ bool Sema::BuiltinComplex(CallExpr *TheCall) {
55585558
/// BuiltinShuffleVector - Handle __builtin_shufflevector.
55595559
// This is declared to take (...), so we have to check everything.
55605560
ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
5561-
if (TheCall->getNumArgs() < 2)
5561+
unsigned NumArgs = TheCall->getNumArgs();
5562+
if (NumArgs < 2)
55625563
return ExprError(Diag(TheCall->getEndLoc(),
55635564
diag::err_typecheck_call_too_few_args_at_least)
55645565
<< 0 /*function call*/ << 2 << TheCall->getNumArgs()
@@ -5567,8 +5568,8 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
55675568
// Determine which of the following types of shufflevector we're checking:
55685569
// 1) unary, vector mask: (lhs, mask)
55695570
// 2) binary, scalar mask: (lhs, rhs, index, ..., index)
5570-
QualType resType = TheCall->getArg(0)->getType();
5571-
unsigned numElements = 0;
5571+
QualType ResType = TheCall->getArg(0)->getType();
5572+
unsigned NumElements = 0;
55725573

55735574
if (!TheCall->getArg(0)->isTypeDependent() &&
55745575
!TheCall->getArg(1)->isTypeDependent()) {
@@ -5582,39 +5583,39 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
55825583
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
55835584
TheCall->getArg(1)->getEndLoc()));
55845585

5585-
numElements = LHSType->castAs<VectorType>()->getNumElements();
5586-
unsigned numResElements = TheCall->getNumArgs() - 2;
5586+
NumElements = LHSType->castAs<VectorType>()->getNumElements();
5587+
unsigned NumResElements = TheCall->getNumArgs() - 2;
55875588

55885589
// Check to see if we have a call with 2 vector arguments, the unary shuffle
55895590
// with mask. If so, verify that RHS is an integer vector type with the
55905591
// same number of elts as lhs.
55915592
if (TheCall->getNumArgs() == 2) {
55925593
if (!RHSType->hasIntegerRepresentation() ||
5593-
RHSType->castAs<VectorType>()->getNumElements() != numElements)
5594+
RHSType->castAs<VectorType>()->getNumElements() != NumElements)
55945595
return ExprError(Diag(TheCall->getBeginLoc(),
55955596
diag::err_vec_builtin_incompatible_vector)
55965597
<< TheCall->getDirectCallee()
5597-
<< /*isMorethantwoArgs*/ false
5598+
<< /*isMoreThanTwoArgs*/ false
55985599
<< SourceRange(TheCall->getArg(1)->getBeginLoc(),
55995600
TheCall->getArg(1)->getEndLoc()));
56005601
} else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
56015602
return ExprError(Diag(TheCall->getBeginLoc(),
56025603
diag::err_vec_builtin_incompatible_vector)
56035604
<< TheCall->getDirectCallee()
5604-
<< /*isMorethantwoArgs*/ false
5605+
<< /*isMoreThanTwoArgs*/ false
56055606
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
56065607
TheCall->getArg(1)->getEndLoc()));
5607-
} else if (numElements != numResElements) {
5608+
} else if (NumElements != NumResElements) {
56085609
QualType eltType = LHSType->castAs<VectorType>()->getElementType();
5609-
resType = resType->isExtVectorType()
5610-
? Context.getExtVectorType(eltType, numResElements)
5611-
: Context.getVectorType(eltType, numResElements,
5610+
ResType = ResType->isExtVectorType()
5611+
? Context.getExtVectorType(eltType, NumResElements)
5612+
: Context.getVectorType(eltType, NumResElements,
56125613
VectorKind::Generic);
56135614
}
56145615
}
56155616

5616-
for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
5617-
Expr *Arg = TheCall->getArg(i);
5617+
for (unsigned I = 2; I != NumArgs; ++I) {
5618+
Expr *Arg = TheCall->getArg(I);
56185619
if (Arg->isTypeDependent() || Arg->isValueDependent())
56195620
continue;
56205621

@@ -5628,21 +5629,21 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
56285629
if (Result->isSigned() && Result->isAllOnes())
56295630
;
56305631
else if (Result->getActiveBits() > 64 ||
5631-
Result->getZExtValue() >= numElements * 2)
5632+
Result->getZExtValue() >= NumElements * 2)
56325633
return ExprError(Diag(TheCall->getBeginLoc(),
56335634
diag::err_shufflevector_argument_too_large)
56345635
<< Arg->getSourceRange());
56355636

5636-
TheCall->setArg(i, ConstantExpr::Create(Context, Arg, APValue(*Result)));
5637+
TheCall->setArg(I, ConstantExpr::Create(Context, Arg, APValue(*Result)));
56375638
}
56385639

5639-
SmallVector<Expr *> exprs;
5640-
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
5641-
exprs.push_back(TheCall->getArg(i));
5642-
TheCall->setArg(i, nullptr);
5640+
SmallVector<Expr *> Exprs;
5641+
for (unsigned I = 0; I != NumArgs; I++) {
5642+
Exprs.push_back(TheCall->getArg(I));
5643+
TheCall->setArg(I, nullptr);
56435644
}
56445645

5645-
return new (Context) ShuffleVectorExpr(Context, exprs, resType,
5646+
return new (Context) ShuffleVectorExpr(Context, Exprs, ResType,
56465647
TheCall->getCallee()->getBeginLoc(),
56475648
TheCall->getRParenLoc());
56485649
}

clang/test/Sema/constant-builtins-vector.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,19 @@ permitted in a constexpr context}}
731731
vector4charConst1,
732732
vector4charConst2, -1, -1, -1, -1);
733733

734+
namespace UnaryShuffleUnsupported {
735+
typedef int vi6 __attribute__((ext_vector_type(2)));
736+
constexpr int foo() { // expected-error {{never produces a constant expression}}
737+
vi6 a = {1,2};
738+
vi6 b = {3,4};
739+
vi6 r = __builtin_shufflevector(a, b); // expected-note 2{{subexpression not valid in a constant expression}}
740+
741+
return r[0] + r[1];
742+
}
743+
static_assert(foo() == 0); // expected-error {{not an integral constant expression}} \
744+
// expected-note {{in call to}}
745+
}
746+
734747
static_assert(__builtin_reduce_add((vector4char){}) == 0);
735748
static_assert(__builtin_reduce_add((vector4char){1, 2, 3, 4}) == 10);
736749
static_assert(__builtin_reduce_add((vector4short){10, 20, 30, 40}) == 100);

0 commit comments

Comments
 (0)