@@ -1970,26 +1970,40 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
1970
1970
// Check if \p Ty is a valid type for the elementwise math builtins. If it is
1971
1971
// not a valid type, emit an error message and return true. Otherwise return
1972
1972
// false.
1973
- static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
1974
- QualType ArgTy, int ArgIndex) {
1975
- if (!ArgTy->getAs<VectorType>() &&
1976
- !ConstantMatrixType::isValidElementType(ArgTy)) {
1977
- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1978
- << ArgIndex << /* vector, integer or float ty*/ 0 << ArgTy;
1979
- }
1980
-
1981
- return false;
1982
- }
1983
-
1984
- static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc,
1985
- QualType ArgTy, int ArgIndex) {
1973
+ static bool
1974
+ checkMathBuiltinElementType(Sema &S, SourceLocation Loc, QualType ArgTy,
1975
+ Sema::EltwiseBuiltinArgTyRestriction ArgTyRestr,
1976
+ int ArgOrdinal) {
1986
1977
QualType EltTy = ArgTy;
1987
1978
if (auto *VecTy = EltTy->getAs<VectorType>())
1988
1979
EltTy = VecTy->getElementType();
1989
1980
1990
- if (!EltTy->isRealFloatingType()) {
1991
- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1992
- << ArgIndex << /* vector or float ty*/ 5 << ArgTy;
1981
+ switch (ArgTyRestr) {
1982
+ case Sema::EltwiseBuiltinArgTyRestriction::None:
1983
+ if (!ArgTy->getAs<VectorType>() &&
1984
+ !ConstantMatrixType::isValidElementType(ArgTy)) {
1985
+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1986
+ << ArgOrdinal << /* vector, integer or float ty*/ 0 << ArgTy;
1987
+ }
1988
+ break;
1989
+ case Sema::EltwiseBuiltinArgTyRestriction::FloatTy:
1990
+ if (!EltTy->isRealFloatingType()) {
1991
+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1992
+ << ArgOrdinal << /* vector or float ty*/ 5 << ArgTy;
1993
+ }
1994
+ break;
1995
+ case Sema::EltwiseBuiltinArgTyRestriction::IntegerTy:
1996
+ if (!EltTy->isIntegerType()) {
1997
+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1998
+ << ArgOrdinal << /* vector or int ty*/ 10 << ArgTy;
1999
+ }
2000
+ break;
2001
+ case Sema::EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy:
2002
+ if (EltTy->isUnsignedIntegerType()) {
2003
+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
2004
+ << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2005
+ }
2006
+ break;
1993
2007
}
1994
2008
1995
2009
return false;
@@ -2696,23 +2710,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2696
2710
2697
2711
// __builtin_elementwise_abs restricts the element type to signed integers or
2698
2712
// floating point types only.
2699
- case Builtin::BI__builtin_elementwise_abs: {
2700
- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2713
+ case Builtin::BI__builtin_elementwise_abs:
2714
+ if (PrepareBuiltinElementwiseMathOneArgCall(
2715
+ TheCall, EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy))
2701
2716
return ExprError();
2702
-
2703
- QualType ArgTy = TheCall->getArg(0)->getType();
2704
- QualType EltTy = ArgTy;
2705
-
2706
- if (auto *VecTy = EltTy->getAs<VectorType>())
2707
- EltTy = VecTy->getElementType();
2708
- if (EltTy->isUnsignedIntegerType()) {
2709
- Diag(TheCall->getArg(0)->getBeginLoc(),
2710
- diag::err_builtin_invalid_arg_type)
2711
- << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2712
- return ExprError();
2713
- }
2714
2717
break;
2715
- }
2716
2718
2717
2719
// These builtins restrict the element type to floating point
2718
2720
// types only.
@@ -2739,81 +2741,46 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2739
2741
case Builtin::BI__builtin_elementwise_tan:
2740
2742
case Builtin::BI__builtin_elementwise_tanh:
2741
2743
case Builtin::BI__builtin_elementwise_trunc:
2742
- case Builtin::BI__builtin_elementwise_canonicalize: {
2743
- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2744
- return ExprError();
2745
-
2746
- QualType ArgTy = TheCall->getArg(0)->getType();
2747
- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2748
- ArgTy, 1))
2744
+ case Builtin::BI__builtin_elementwise_canonicalize:
2745
+ if (PrepareBuiltinElementwiseMathOneArgCall(
2746
+ TheCall, EltwiseBuiltinArgTyRestriction::FloatTy))
2749
2747
return ExprError();
2750
2748
break;
2751
- }
2752
- case Builtin::BI__builtin_elementwise_fma: {
2749
+ case Builtin::BI__builtin_elementwise_fma:
2753
2750
if (BuiltinElementwiseTernaryMath(TheCall))
2754
2751
return ExprError();
2755
2752
break;
2756
- }
2757
2753
2758
2754
// These builtins restrict the element type to floating point
2759
2755
// types only, and take in two arguments.
2760
2756
case Builtin::BI__builtin_elementwise_minimum:
2761
2757
case Builtin::BI__builtin_elementwise_maximum:
2762
2758
case Builtin::BI__builtin_elementwise_atan2:
2763
2759
case Builtin::BI__builtin_elementwise_fmod:
2764
- case Builtin::BI__builtin_elementwise_pow: {
2765
- if (BuiltinElementwiseMath(TheCall, /*FPOnly=*/true))
2760
+ case Builtin::BI__builtin_elementwise_pow:
2761
+ if (BuiltinElementwiseMath(TheCall,
2762
+ EltwiseBuiltinArgTyRestriction::FloatTy))
2766
2763
return ExprError();
2767
2764
break;
2768
- }
2769
-
2770
2765
// These builtins restrict the element type to integer
2771
2766
// types only.
2772
2767
case Builtin::BI__builtin_elementwise_add_sat:
2773
- case Builtin::BI__builtin_elementwise_sub_sat: {
2774
- if (BuiltinElementwiseMath(TheCall))
2775
- return ExprError();
2776
-
2777
- const Expr *Arg = TheCall->getArg(0);
2778
- QualType ArgTy = Arg->getType();
2779
- QualType EltTy = ArgTy;
2780
-
2781
- if (auto *VecTy = EltTy->getAs<VectorType>())
2782
- EltTy = VecTy->getElementType();
2783
-
2784
- if (!EltTy->isIntegerType()) {
2785
- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2786
- << 1 << /* integer ty */ 6 << ArgTy;
2768
+ case Builtin::BI__builtin_elementwise_sub_sat:
2769
+ if (BuiltinElementwiseMath(TheCall,
2770
+ EltwiseBuiltinArgTyRestriction::IntegerTy))
2787
2771
return ExprError();
2788
- }
2789
2772
break;
2790
- }
2791
-
2792
2773
case Builtin::BI__builtin_elementwise_min:
2793
2774
case Builtin::BI__builtin_elementwise_max:
2794
2775
if (BuiltinElementwiseMath(TheCall))
2795
2776
return ExprError();
2796
2777
break;
2797
2778
case Builtin::BI__builtin_elementwise_popcount:
2798
- case Builtin::BI__builtin_elementwise_bitreverse: {
2799
- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2800
- return ExprError();
2801
-
2802
- const Expr *Arg = TheCall->getArg(0);
2803
- QualType ArgTy = Arg->getType();
2804
- QualType EltTy = ArgTy;
2805
-
2806
- if (auto *VecTy = EltTy->getAs<VectorType>())
2807
- EltTy = VecTy->getElementType();
2808
-
2809
- if (!EltTy->isIntegerType()) {
2810
- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2811
- << 1 << /* integer ty */ 6 << ArgTy;
2779
+ case Builtin::BI__builtin_elementwise_bitreverse:
2780
+ if (PrepareBuiltinElementwiseMathOneArgCall(
2781
+ TheCall, EltwiseBuiltinArgTyRestriction::IntegerTy))
2812
2782
return ExprError();
2813
- }
2814
2783
break;
2815
- }
2816
-
2817
2784
case Builtin::BI__builtin_elementwise_copysign: {
2818
2785
if (checkArgCount(TheCall, 2))
2819
2786
return ExprError();
@@ -2825,10 +2792,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2825
2792
2826
2793
QualType MagnitudeTy = Magnitude.get()->getType();
2827
2794
QualType SignTy = Sign.get()->getType();
2828
- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2829
- MagnitudeTy, 1) ||
2830
- checkFPMathBuiltinElementType(*this, TheCall->getArg(1)->getBeginLoc(),
2831
- SignTy, 2)) {
2795
+ if (checkMathBuiltinElementType(
2796
+ *this, TheCall->getArg(0)->getBeginLoc(), MagnitudeTy,
2797
+ EltwiseBuiltinArgTyRestriction::FloatTy, 1) ||
2798
+ checkMathBuiltinElementType(
2799
+ *this, TheCall->getArg(1)->getBeginLoc(), SignTy,
2800
+ EltwiseBuiltinArgTyRestriction::FloatTy, 2)) {
2832
2801
return ExprError();
2833
2802
}
2834
2803
@@ -15278,7 +15247,8 @@ static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
15278
15247
return S.UsualUnaryFPConversions(Res.get());
15279
15248
}
15280
15249
15281
- bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
15250
+ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(
15251
+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr) {
15282
15252
if (checkArgCount(TheCall, 1))
15283
15253
return true;
15284
15254
@@ -15289,15 +15259,17 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
15289
15259
TheCall->setArg(0, A.get());
15290
15260
QualType TyA = A.get()->getType();
15291
15261
15292
- if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA, 1))
15262
+ if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA,
15263
+ ArgTyRestr, 1))
15293
15264
return true;
15294
15265
15295
15266
TheCall->setType(TyA);
15296
15267
return false;
15297
15268
}
15298
15269
15299
- bool Sema::BuiltinElementwiseMath(CallExpr *TheCall, bool FPOnly) {
15300
- if (auto Res = BuiltinVectorMath(TheCall, FPOnly); Res.has_value()) {
15270
+ bool Sema::BuiltinElementwiseMath(CallExpr *TheCall,
15271
+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
15272
+ if (auto Res = BuiltinVectorMath(TheCall, ArgTyRestr); Res.has_value()) {
15301
15273
TheCall->setType(*Res);
15302
15274
return false;
15303
15275
}
@@ -15330,8 +15302,9 @@ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
15330
15302
return false;
15331
15303
}
15332
15304
15333
- std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
15334
- bool FPOnly) {
15305
+ std::optional<QualType>
15306
+ Sema::BuiltinVectorMath(CallExpr *TheCall,
15307
+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
15335
15308
if (checkArgCount(TheCall, 2))
15336
15309
return std::nullopt;
15337
15310
@@ -15352,26 +15325,21 @@ std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
15352
15325
QualType TyA = Args[0]->getType();
15353
15326
QualType TyB = Args[1]->getType();
15354
15327
15328
+ if (checkMathBuiltinElementType(*this, LocA, TyA, ArgTyRestr, 1))
15329
+ return std::nullopt;
15330
+
15355
15331
if (TyA.getCanonicalType() != TyB.getCanonicalType()) {
15356
15332
Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
15357
15333
return std::nullopt;
15358
15334
}
15359
15335
15360
- if (FPOnly) {
15361
- if (checkFPMathBuiltinElementType(*this, LocA, TyA, 1))
15362
- return std::nullopt;
15363
- } else {
15364
- if (checkMathBuiltinElementType(*this, LocA, TyA, 1))
15365
- return std::nullopt;
15366
- }
15367
-
15368
15336
TheCall->setArg(0, Args[0]);
15369
15337
TheCall->setArg(1, Args[1]);
15370
15338
return TyA;
15371
15339
}
15372
15340
15373
- bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
15374
- bool CheckForFloatArgs ) {
15341
+ bool Sema::BuiltinElementwiseTernaryMath(
15342
+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr ) {
15375
15343
if (checkArgCount(TheCall, 3))
15376
15344
return true;
15377
15345
@@ -15391,20 +15359,11 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
15391
15359
Args[I] = Converted.get();
15392
15360
}
15393
15361
15394
- if (CheckForFloatArgs) {
15395
- int ArgOrdinal = 1;
15396
- for (Expr *Arg : Args) {
15397
- if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(),
15398
- Arg->getType(), ArgOrdinal++))
15399
- return true;
15400
- }
15401
- } else {
15402
- int ArgOrdinal = 1;
15403
- for (Expr *Arg : Args) {
15404
- if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
15405
- ArgOrdinal++))
15406
- return true;
15407
- }
15362
+ int ArgOrdinal = 1;
15363
+ for (Expr *Arg : Args) {
15364
+ if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
15365
+ ArgTyRestr, ArgOrdinal++))
15366
+ return true;
15408
15367
}
15409
15368
15410
15369
for (int I = 1; I < 3; ++I) {
0 commit comments