Skip to content

Commit ec40097

Browse files
committed
[clang][Interp] Implement __builtin_{ctz,clz}g
1 parent 990c4bc commit ec40097

File tree

2 files changed

+160
-6
lines changed

2 files changed

+160
-6
lines changed

clang/lib/AST/Interp/InterpBuiltin.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
namespace clang {
1717
namespace interp {
1818

19+
static unsigned callArgSize(const InterpState &S, const CallExpr *C) {
20+
unsigned O = 0;
21+
22+
for (const Expr *E : C->arguments()) {
23+
O += align(primSize(*S.getContext().classify(E)));
24+
}
25+
26+
return O;
27+
}
28+
1929
template <typename T>
2030
static T getParam(const InterpFrame *Frame, unsigned Index) {
2131
assert(Frame->getFunction()->getNumParams() > Index);
@@ -816,18 +826,30 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
816826
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
817827
const InterpFrame *Frame, const Function *Func,
818828
const CallExpr *Call) {
829+
unsigned CallSize = callArgSize(S, Call);
819830
unsigned BuiltinOp = Func->getBuiltinID();
820831
PrimType ValT = *S.getContext().classify(Call->getArg(0));
821-
const APSInt &Val = peekToAPSInt(S.Stk, ValT);
832+
const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
822833

823834
// When the argument is 0, the result of GCC builtins is undefined, whereas
824835
// for Microsoft intrinsics, the result is the bit-width of the argument.
825836
bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
826837
BuiltinOp != Builtin::BI__lzcnt &&
827838
BuiltinOp != Builtin::BI__lzcnt64;
828839

829-
if (ZeroIsUndefined && Val == 0)
830-
return false;
840+
if (Val == 0) {
841+
if (Func->getBuiltinID() == Builtin::BI__builtin_clzg &&
842+
Call->getNumArgs() == 2) {
843+
// We have a fallback parameter.
844+
PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
845+
const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
846+
pushInteger(S, Fallback, Call->getType());
847+
return true;
848+
}
849+
850+
if (ZeroIsUndefined)
851+
return false;
852+
}
831853

832854
pushInteger(S, Val.countl_zero(), Call->getType());
833855
return true;
@@ -836,11 +858,21 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
836858
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
837859
const InterpFrame *Frame, const Function *Func,
838860
const CallExpr *Call) {
861+
unsigned CallSize = callArgSize(S, Call);
839862
PrimType ValT = *S.getContext().classify(Call->getArg(0));
840-
const APSInt &Val = peekToAPSInt(S.Stk, ValT);
841-
842-
if (Val == 0)
863+
const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
864+
865+
if (Val == 0) {
866+
if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg &&
867+
Call->getNumArgs() == 2) {
868+
// We have a fallback parameter.
869+
PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
870+
const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
871+
pushInteger(S, Fallback, Call->getType());
872+
return true;
873+
}
843874
return false;
875+
}
844876

845877
pushInteger(S, Val.countr_zero(), Call->getType());
846878
return true;
@@ -1223,6 +1255,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
12231255
case Builtin::BI__builtin_clzl:
12241256
case Builtin::BI__builtin_clzll:
12251257
case Builtin::BI__builtin_clzs:
1258+
case Builtin::BI__builtin_clzg:
12261259
case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
12271260
case Builtin::BI__lzcnt:
12281261
case Builtin::BI__lzcnt64:
@@ -1234,6 +1267,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
12341267
case Builtin::BI__builtin_ctzl:
12351268
case Builtin::BI__builtin_ctzll:
12361269
case Builtin::BI__builtin_ctzs:
1270+
case Builtin::BI__builtin_ctzg:
12371271
if (!interp__builtin_ctz(S, OpPC, Frame, F, Call))
12381272
return false;
12391273
break;

clang/test/AST/Interp/builtin-functions.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ void test_noexcept(int *i) {
482482
#undef TEST_TYPE
483483
} // end namespace test_launder
484484

485+
486+
/// FIXME: The commented out tests here use a IntAP value and fail.
487+
/// This currently means we will leak the IntAP value since nothing cleans it up.
485488
namespace clz {
486489
char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1];
487490
char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1];
@@ -492,6 +495,63 @@ namespace clz {
492495
char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1];
493496
char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1];
494497
char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1];
498+
499+
int clz10 = __builtin_clzg((unsigned char)0);
500+
char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1];
501+
char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1];
502+
char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1];
503+
char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1];
504+
char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1];
505+
char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1];
506+
char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1];
507+
int clz18 = __builtin_clzg((unsigned short)0);
508+
char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1];
509+
char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1];
510+
char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1];
511+
char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1];
512+
char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1];
513+
char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1];
514+
char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1];
515+
int clz26 = __builtin_clzg(0U);
516+
char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1];
517+
char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1];
518+
char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1];
519+
char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1];
520+
char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1];
521+
char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
522+
char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1];
523+
int clz34 = __builtin_clzg(0UL);
524+
char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1];
525+
char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1];
526+
char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1];
527+
char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1];
528+
char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1];
529+
char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1];
530+
char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1];
531+
int clz42 = __builtin_clzg(0ULL);
532+
char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1];
533+
char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1];
534+
char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1];
535+
char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1];
536+
char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1];
537+
char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1];
538+
char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1];
539+
#ifdef __SIZEOF_INT128__
540+
// int clz50 = __builtin_clzg((unsigned __int128)0);
541+
char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
542+
char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1];
543+
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
544+
char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1];
545+
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
546+
#endif
547+
#ifndef __AVR__
548+
// int clz58 = __builtin_clzg((unsigned _BitInt(128))0);
549+
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
550+
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
551+
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
552+
char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
553+
char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
554+
#endif
495555
}
496556

497557
namespace ctz {
@@ -502,6 +562,66 @@ namespace ctz {
502562
char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1];
503563
char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1];
504564
char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1];
565+
int ctz8 = __builtin_ctzg((unsigned char)0);
566+
char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1];
567+
char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1];
568+
char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1];
569+
char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1];
570+
char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1];
571+
char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1];
572+
char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1];
573+
int ctz16 = __builtin_ctzg((unsigned short)0);
574+
char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1];
575+
char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1];
576+
char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1];
577+
char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1];
578+
char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1];
579+
char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1];
580+
char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1];
581+
int ctz24 = __builtin_ctzg(0U);
582+
char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1];
583+
char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1];
584+
char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1];
585+
char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1];
586+
char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1];
587+
char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1];
588+
char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1];
589+
int ctz32 = __builtin_ctzg(0UL);
590+
char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1];
591+
char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1];
592+
char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1];
593+
char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1];
594+
char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1];
595+
char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1];
596+
char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1];
597+
int ctz40 = __builtin_ctzg(0ULL);
598+
char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1];
599+
char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1];
600+
char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1];
601+
char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1];
602+
char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1];
603+
char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1];
604+
char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1];
605+
#ifdef __SIZEOF_INT128__
606+
// int ctz48 = __builtin_ctzg((unsigned __int128)0);
607+
char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
608+
char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1];
609+
char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1];
610+
char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1];
611+
char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1];
612+
char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1];
613+
char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1];
614+
#endif
615+
#ifndef __AVR__
616+
// int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0);
617+
char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
618+
char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1];
619+
char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1];
620+
char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1];
621+
char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1];
622+
char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
623+
char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
624+
#endif
505625
}
506626

507627
namespace bswap {

0 commit comments

Comments
 (0)