Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3986,6 +3986,10 @@ bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {

template <class Emitter>
bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
// FIXME: Unary shuffle with mask not currently supported.
if (E->getNumSubExprs() == 2)
return this->emitInvalid(E);

assert(Initializing);
assert(E->getNumSubExprs() > 2);

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12160,6 +12160,9 @@ static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
}

bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
// FIXME: Unary shuffle with mask not currently supported.
if (E->getNumSubExprs() == 2)
return Error(E);
APValue VecVal1;
const Expr *Vec1 = E->getExpr(0);
if (!EvaluateAsRValue(Info, Vec1, VecVal1))
Expand Down
55 changes: 27 additions & 28 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5558,17 +5558,18 @@ bool Sema::BuiltinComplex(CallExpr *TheCall) {
/// BuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
if (TheCall->getNumArgs() < 2)
unsigned NumArgs = TheCall->getNumArgs();
if (NumArgs < 2)
return ExprError(Diag(TheCall->getEndLoc(),
diag::err_typecheck_call_too_few_args_at_least)
<< 0 /*function call*/ << 2 << TheCall->getNumArgs()
<< 0 /*function call*/ << 2 << NumArgs
<< /*is non object*/ 0 << TheCall->getSourceRange());

// Determine which of the following types of shufflevector we're checking:
// 1) unary, vector mask: (lhs, mask)
// 2) binary, scalar mask: (lhs, rhs, index, ..., index)
QualType resType = TheCall->getArg(0)->getType();
unsigned numElements = 0;
QualType ResType = TheCall->getArg(0)->getType();
unsigned NumElements = 0;

if (!TheCall->getArg(0)->isTypeDependent() &&
!TheCall->getArg(1)->isTypeDependent()) {
Expand All @@ -5578,43 +5579,43 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
if (!LHSType->isVectorType() || !RHSType->isVectorType())
return ExprError(
Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
<< TheCall->getDirectCallee() << /*isMoreThanTwoArgs*/ false
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
TheCall->getArg(1)->getEndLoc()));

numElements = LHSType->castAs<VectorType>()->getNumElements();
unsigned numResElements = TheCall->getNumArgs() - 2;
NumElements = LHSType->castAs<VectorType>()->getNumElements();
unsigned NumResElements = NumArgs - 2;

// Check to see if we have a call with 2 vector arguments, the unary shuffle
// with mask. If so, verify that RHS is an integer vector type with the
// same number of elts as lhs.
if (TheCall->getNumArgs() == 2) {
if (NumArgs == 2) {
if (!RHSType->hasIntegerRepresentation() ||
RHSType->castAs<VectorType>()->getNumElements() != numElements)
RHSType->castAs<VectorType>()->getNumElements() != NumElements)
return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< /*isMorethantwoArgs*/ false
<< /*isMoreThanTwoArgs*/ false
<< SourceRange(TheCall->getArg(1)->getBeginLoc(),
TheCall->getArg(1)->getEndLoc()));
} else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee()
<< /*isMorethantwoArgs*/ false
<< /*isMoreThanTwoArgs*/ false
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
TheCall->getArg(1)->getEndLoc()));
} else if (numElements != numResElements) {
QualType eltType = LHSType->castAs<VectorType>()->getElementType();
resType = resType->isExtVectorType()
? Context.getExtVectorType(eltType, numResElements)
: Context.getVectorType(eltType, numResElements,
} else if (NumElements != NumResElements) {
QualType EltType = LHSType->castAs<VectorType>()->getElementType();
ResType = ResType->isExtVectorType()
? Context.getExtVectorType(EltType, NumResElements)
: Context.getVectorType(EltType, NumResElements,
VectorKind::Generic);
}
}

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

Expand All @@ -5628,23 +5629,21 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
if (Result->isSigned() && Result->isAllOnes())
;
else if (Result->getActiveBits() > 64 ||
Result->getZExtValue() >= numElements * 2)
Result->getZExtValue() >= NumElements * 2)
return ExprError(Diag(TheCall->getBeginLoc(),
diag::err_shufflevector_argument_too_large)
<< Arg->getSourceRange());

TheCall->setArg(i, ConstantExpr::Create(Context, Arg, APValue(*Result)));
TheCall->setArg(I, ConstantExpr::Create(Context, Arg, APValue(*Result)));
}

SmallVector<Expr *> exprs;
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
exprs.push_back(TheCall->getArg(i));
TheCall->setArg(i, nullptr);
}
auto *Result = new (Context) ShuffleVectorExpr(
Context, ArrayRef(TheCall->getArgs(), NumArgs), ResType,
TheCall->getCallee()->getBeginLoc(), TheCall->getRParenLoc());

return new (Context) ShuffleVectorExpr(Context, exprs, resType,
TheCall->getCallee()->getBeginLoc(),
TheCall->getRParenLoc());
// All moved to Result.
TheCall->shrinkNumArgs(0);
return Result;
}

ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
Expand Down
13 changes: 13 additions & 0 deletions clang/test/Sema/constant-builtins-vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,19 @@ permitted in a constexpr context}}
vector4charConst1,
vector4charConst2, -1, -1, -1, -1);

namespace UnaryShuffleUnsupported {
typedef int vi6 __attribute__((ext_vector_type(2)));
constexpr int foo() { // expected-error {{never produces a constant expression}}
vi6 a = {1,2};
vi6 b = {3,4};
vi6 r = __builtin_shufflevector(a, b); // expected-note 2{{subexpression not valid in a constant expression}}

return r[0] + r[1];
}
static_assert(foo() == 0); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}
}

static_assert(__builtin_reduce_add((vector4char){}) == 0);
static_assert(__builtin_reduce_add((vector4char){1, 2, 3, 4}) == 10);
static_assert(__builtin_reduce_add((vector4short){10, 20, 30, 40}) == 100);
Expand Down
Loading