Skip to content

Commit 9493c0f

Browse files
Following the review of sethp, I have made the following changes:
-- Added diagnostic for the undefined shuffle of -1 -- Validated support for _BitInt -- A bunch of other minnor tweaks here and there
1 parent 8273abc commit 9493c0f

File tree

4 files changed

+70
-55
lines changed

4 files changed

+70
-55
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10330,6 +10330,8 @@ def err_shufflevector_nonconstant_argument : Error<
1033010330
def err_shufflevector_argument_too_large : Error<
1033110331
"index for __builtin_shufflevector must be less than the total number "
1033210332
"of vector elements">;
10333+
def err_shufflevector_minus_one_is_undefined_behavior_constexpr : Error<
10334+
"index for __builtin_shufflevector must be within the bounds of the input vectors in a constexpr context. An index of -1 at position %0 was found. -1 is only allowed at runtime.">;
1033310335

1033410336
def err_convertvector_non_vector : Error<
1033510337
"first argument to __builtin_convertvector must be a vector">;

clang/lib/AST/ExprConstant.cpp

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,8 +2706,11 @@ static bool checkFloatingPointResult(EvalInfo &Info, const Expr *E,
27062706
static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E,
27072707
QualType SrcType, QualType DestType,
27082708
APFloat &Result) {
2709-
assert(isa<CastExpr>(E) || isa<CompoundAssignOperator>(E) ||
2710-
isa<ConvertVectorExpr>(E));
2709+
assert((isa<CastExpr>(E) || isa<CompoundAssignOperator>(E) ||
2710+
isa<ConvertVectorExpr>(E)) &&
2711+
"HandleFloatToFloatCast has been checked with only CastExpr, "
2712+
"CompoundAssignOperator and ConvertVectorExpr. Please either validate "
2713+
"the new expression or address the root cause of this usage.");
27112714
llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
27122715
APFloat::opStatus St;
27132716
APFloat Value = Result;
@@ -10714,7 +10717,7 @@ namespace {
1071410717
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
1071510718

1071610719
// FIXME: Missing: conditional operator (for GNU
10717-
// conditional select), shufflevector, ExtVectorElementExpr
10720+
// conditional select), ExtVectorElementExpr
1071810721
};
1071910722
} // end anonymous namespace
1072010723

@@ -10965,27 +10968,10 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
1096510968
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
1096610969
}
1096710970

10968-
static bool EvaluateVectorOrLValue(APValue &Result, EvalInfo &Info,
10969-
const Expr *E, const QualType &Type) {
10970-
if (!Evaluate(Result, Info, E))
10971-
return false;
10972-
10973-
if (Result.isLValue()) {
10974-
// Source of the data is an lvalue; Manually handle the lvalue as if
10975-
// it was an rvalue to get the current APValue.
10976-
LValue LValueFound;
10977-
LValueFound.setFrom(Info.Ctx, Result);
10978-
if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
10979-
return false;
10980-
}
10981-
10982-
return Result.isVector();
10983-
}
10984-
10985-
static bool handleVectorConversion(EvalInfo &Info, const FPOptions FPO,
10986-
const Expr *E, QualType SourceTy,
10987-
QualType DestTy, APValue const &Original,
10988-
APValue &Result) {
10971+
static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
10972+
const Expr *E, QualType SourceTy,
10973+
QualType DestTy, APValue const &Original,
10974+
APValue &Result) {
1098910975
if (SourceTy->isIntegerType()) {
1099010976
if (DestTy->isRealFloatingType()) {
1099110977
Result = APValue(APFloat(0.0));
@@ -11015,7 +11001,7 @@ static bool handleVectorConversion(EvalInfo &Info, const FPOptions FPO,
1101511001
bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
1101611002
APValue Source;
1101711003
QualType SourceVecType = E->getSrcExpr()->getType();
11018-
if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
11004+
if (!EvaluateAsRValue(Info, E->getSrcExpr(), Source))
1101911005
return false;
1102011006

1102111007
QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
@@ -11028,8 +11014,8 @@ bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
1102811014
ResultElements.reserve(SourceLen);
1102911015
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
1103011016
APValue Elt;
11031-
if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
11032-
Source.getVectorElt(EltNum), Elt))
11017+
if (!handleVectorElementCast(Info, FPO, E, SourceTy, DestTy,
11018+
Source.getVectorElt(EltNum), Elt))
1103311019
return false;
1103411020
ResultElements.push_back(std::move(Elt));
1103511021
}
@@ -11041,21 +11027,24 @@ static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
1104111027
QualType ElemType, APValue const &VecVal1,
1104211028
APValue const &VecVal2, unsigned EltNum,
1104311029
APValue &Result) {
11044-
unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
11045-
11046-
Expr const *IndexExpr = E->getExpr(2 + EltNum);
11047-
APSInt IndexVal;
11048-
if (!EvaluateInteger(IndexExpr, IndexVal, Info))
11049-
return false;
11030+
unsigned const TotalElementsInInputVector = VecVal1.getVectorLength();
1105011031

11051-
uint32_t index = IndexVal.getZExtValue();
11032+
APSInt IndexVal = E->getShuffleMaskIdx(Info.Ctx, EltNum);
11033+
int64_t index = IndexVal.getExtValue();
1105211034
// The spec says that -1 should be treated as undef for optimizations,
1105311035
// but in constexpr we need to choose a value. We'll choose 0.
11054-
if (index >= TotalElementsInAVector * 2)
11055-
index = 0;
11036+
if (index == -1) {
11037+
Info.FFDiag(
11038+
E, diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
11039+
<< EltNum;
11040+
return false;
11041+
}
11042+
11043+
if (index < 0 || index >= TotalElementsInInputVector * 2)
11044+
llvm_unreachable("Out of bounds shuffle index");
1105611045

11057-
if (index >= TotalElementsInAVector)
11058-
Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
11046+
if (index >= TotalElementsInInputVector)
11047+
Result = VecVal2.getVectorElt(index - TotalElementsInInputVector);
1105911048
else
1106011049
Result = VecVal1.getVectorElt(index);
1106111050
return true;
@@ -11064,11 +11053,11 @@ static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
1106411053
bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
1106511054
APValue VecVal1;
1106611055
const Expr *Vec1 = E->getExpr(0);
11067-
if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
11056+
if (!EvaluateAsRValue(Info, Vec1, VecVal1))
1106811057
return false;
1106911058
APValue VecVal2;
1107011059
const Expr *Vec2 = E->getExpr(1);
11071-
if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
11060+
if (!EvaluateAsRValue(Info, Vec2, VecVal2))
1107211061
return false;
1107311062

1107411063
VectorType const *DestVecTy = E->getType()->castAs<VectorType>();

clang/test/Sema/constant_builtins_vector.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
2-
// expected-no-diagnostics
1+
// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension %s
32

43
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
54
#define LITTLE_END 1
@@ -9,18 +8,29 @@
98
#error "huh?"
109
#endif
1110

11+
// We also support _BitInt as long as it is >=8 and a power of 2.
12+
typedef _BitInt(8) BitInt8;
13+
typedef _BitInt(32) BitInt32;
14+
typedef _BitInt(128) BitInt128;
15+
1216
typedef double vector4double __attribute__((__vector_size__(32)));
1317
typedef float vector4float __attribute__((__vector_size__(16)));
1418
typedef long long vector4long __attribute__((__vector_size__(32)));
1519
typedef int vector4int __attribute__((__vector_size__(16)));
1620
typedef short vector4short __attribute__((__vector_size__(8)));
1721
typedef char vector4char __attribute__((__vector_size__(4)));
22+
typedef BitInt8 vector4BitInt8 __attribute__((__vector_size__(4)));
23+
typedef BitInt32 vector4BitInt32 __attribute__((__vector_size__(16)));
24+
typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64)));
1825
typedef double vector8double __attribute__((__vector_size__(64)));
1926
typedef float vector8float __attribute__((__vector_size__(32)));
2027
typedef long long vector8long __attribute__((__vector_size__(64)));
2128
typedef int vector8int __attribute__((__vector_size__(32)));
2229
typedef short vector8short __attribute__((__vector_size__(16)));
2330
typedef char vector8char __attribute__((__vector_size__(8)));
31+
typedef BitInt8 vector8BitInt8 __attribute__((__vector_size__(8)));
32+
typedef BitInt32 vector8BitInt32 __attribute__((__vector_size__(32)));
33+
typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128)));
2434

2535
#define CHECK_NUM(__size, __typeFrom, __typeTo, ...) \
2636
constexpr vector##__size##__typeTo \
@@ -34,6 +44,9 @@ typedef char vector8char __attribute__((__vector_size__(8)));
3444
CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__) \
3545
CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__) \
3646
CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__) \
47+
CHECK_NUM(__size, __typeFrom, BitInt8, __VA_ARGS__) \
48+
CHECK_NUM(__size, __typeFrom, BitInt32, __VA_ARGS__) \
49+
CHECK_NUM(__size, __typeFrom, BitInt128, __VA_ARGS__) \
3750
static_assert( \
3851
__builtin_bit_cast( \
3952
unsigned, \
@@ -56,7 +69,10 @@ typedef char vector8char __attribute__((__vector_size__(8)));
5669
CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__) \
5770
CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) \
5871
CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__) \
59-
CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
72+
CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__) \
73+
CHECK_TO_ALL_TYPES(__size, BitInt8, __VA_ARGS__) \
74+
CHECK_TO_ALL_TYPES(__size, BitInt32, __VA_ARGS__) \
75+
CHECK_TO_ALL_TYPES(__size, BitInt128, __VA_ARGS__)
6076

6177
CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
6278
CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
@@ -77,23 +93,28 @@ constexpr vector4char vectorShuffle2 =
7793
__builtin_shufflevector(vector4charConst1, vector4charConst2, 4, 5, 6, 7);
7894
static_assert(__builtin_bit_cast(unsigned, vectorShuffle2) ==
7995
(LITTLE_END ? 0x07060504 : 0x04050607));
80-
constexpr vector4char vectorShuffle3 = __builtin_shufflevector(
81-
vector4charConst1, vector4charConst2, -1, -1, -1, -1);
82-
static_assert(__builtin_bit_cast(unsigned, vectorShuffle3) ==
83-
(LITTLE_END ? 0x00000000 : 0x00000000));
84-
constexpr vector4char vectorShuffle4 =
96+
constexpr vector4char vectorShuffle3 =
8597
__builtin_shufflevector(vector4charConst1, vector4charConst2, 0, 2, 4, 6);
86-
static_assert(__builtin_bit_cast(unsigned, vectorShuffle4) ==
98+
static_assert(__builtin_bit_cast(unsigned, vectorShuffle3) ==
8799
(LITTLE_END ? 0x06040200 : 0x00020406));
88-
constexpr vector8char vectorShuffle5 = __builtin_shufflevector(
100+
constexpr vector8char vectorShuffle4 = __builtin_shufflevector(
89101
vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
90-
static_assert(__builtin_bit_cast(unsigned long long, vectorShuffle5) ==
102+
static_assert(__builtin_bit_cast(unsigned long long, vectorShuffle4) ==
91103
(LITTLE_END ? 0x0E0C0A080E0C0A08 : 0x080A0C0E080A0C0E));
92-
constexpr vector4char vectorShuffle6 =
104+
constexpr vector4char vectorShuffle5 =
93105
__builtin_shufflevector(vector8intConst, vector8intConst, 0, 2, 4, 6);
94-
static_assert(__builtin_bit_cast(unsigned, vectorShuffle6) ==
106+
static_assert(__builtin_bit_cast(unsigned, vectorShuffle5) ==
95107
(LITTLE_END ? 0x0E0C0A08 : 0x080A0C0E));
96-
constexpr vector8char vectorShuffle7 = __builtin_shufflevector(
108+
constexpr vector8char vectorShuffle6 = __builtin_shufflevector(
97109
vector4charConst1, vector4charConst2, 0, 2, 4, 6, 1, 3, 5, 7);
98-
static_assert(__builtin_bit_cast(unsigned long long, vectorShuffle7) ==
110+
static_assert(__builtin_bit_cast(unsigned long long, vectorShuffle6) ==
99111
(LITTLE_END ? 0x0705030106040200 : 0x0002040601030507));
112+
113+
constexpr vector4char
114+
vectorShuffleFail1 = // expected-error {{constexpr variable 'vectorShuffleFail1'\
115+
must be initialized by a constant expression}}
116+
__builtin_shufflevector( // expected-error {{index for __builtin_shufflevector must be within\
117+
the bounds of the input vectors in a constexpr context. An index of\
118+
-1 at position 0 was found. -1 is only allowed at runtime.}}
119+
vector4charConst1,
120+
vector4charConst2, -1, -1, -1, -1);

clang/test/Sema/convertvector.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ vector8float foo3(double x) {
1515
return __builtin_convertvector(x, vector8float); // expected-error {{must be a vector}}
1616
}
1717

18+
float foo4(float x) {
19+
return __builtin_convertvector(x, float); // expected-error {{first argument to __builtin_convertvector must be a vector}}
20+
}

0 commit comments

Comments
 (0)