Skip to content

Commit 3defe8f

Browse files
authored
[clang][Interp] Implement __builtin_bitreverse (#71687)
Since the return value of this function is slightly more involved than the void/bool/int/size_t return values we've seen so far, also refactor this.
1 parent 894a387 commit 3defe8f

File tree

2 files changed

+147
-67
lines changed

2 files changed

+147
-67
lines changed

clang/lib/AST/Interp/InterpBuiltin.cpp

Lines changed: 140 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,54 @@ static void pushInt(InterpState &S, int32_t Val) {
5959
llvm_unreachable("Int isn't 16 or 32 bit?");
6060
}
6161

62-
static bool retInt(InterpState &S, CodePtr OpPC, APValue &Result) {
63-
PrimType IntType = getIntPrimType(S);
64-
if (IntType == PT_Sint32)
65-
return Ret<PT_Sint32>(S, OpPC, Result);
66-
else if (IntType == PT_Sint16)
67-
return Ret<PT_Sint16>(S, OpPC, Result);
68-
llvm_unreachable("Int isn't 16 or 32 bit?");
62+
static void pushAPSInt(InterpState &S, const APSInt &Val) {
63+
bool Signed = Val.isSigned();
64+
65+
if (Signed) {
66+
switch (Val.getBitWidth()) {
67+
case 64:
68+
S.Stk.push<Integral<64, true>>(
69+
Integral<64, true>::from(Val.getSExtValue()));
70+
break;
71+
case 32:
72+
S.Stk.push<Integral<32, true>>(
73+
Integral<32, true>::from(Val.getSExtValue()));
74+
break;
75+
case 16:
76+
S.Stk.push<Integral<16, true>>(
77+
Integral<16, true>::from(Val.getSExtValue()));
78+
break;
79+
case 8:
80+
S.Stk.push<Integral<8, true>>(
81+
Integral<8, true>::from(Val.getSExtValue()));
82+
break;
83+
default:
84+
llvm_unreachable("Invalid integer bitwidth");
85+
}
86+
return;
87+
}
88+
89+
// Unsigned.
90+
switch (Val.getBitWidth()) {
91+
case 64:
92+
S.Stk.push<Integral<64, false>>(
93+
Integral<64, false>::from(Val.getZExtValue()));
94+
break;
95+
case 32:
96+
S.Stk.push<Integral<32, false>>(
97+
Integral<32, false>::from(Val.getZExtValue()));
98+
break;
99+
case 16:
100+
S.Stk.push<Integral<16, false>>(
101+
Integral<16, false>::from(Val.getZExtValue()));
102+
break;
103+
case 8:
104+
S.Stk.push<Integral<8, false>>(
105+
Integral<8, false>::from(Val.getZExtValue()));
106+
break;
107+
default:
108+
llvm_unreachable("Invalid integer bitwidth");
109+
}
69110
}
70111

71112
static void pushSizeT(InterpState &S, uint64_t Val) {
@@ -87,20 +128,29 @@ static void pushSizeT(InterpState &S, uint64_t Val) {
87128
}
88129
}
89130

90-
static bool retSizeT(InterpState &S, CodePtr OpPC, APValue &Result) {
91-
const TargetInfo &TI = S.getCtx().getTargetInfo();
92-
unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
93-
94-
switch (SizeTWidth) {
95-
case 64:
96-
return Ret<PT_Uint64>(S, OpPC, Result);
97-
case 32:
98-
return Ret<PT_Uint32>(S, OpPC, Result);
99-
case 16:
100-
return Ret<PT_Uint16>(S, OpPC, Result);
131+
static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,
132+
std::optional<PrimType> &T) {
133+
if (!T)
134+
return RetVoid(S, OpPC, Result);
135+
136+
#define RET_CASE(X) \
137+
case X: \
138+
return Ret<X>(S, OpPC, Result);
139+
switch (*T) {
140+
RET_CASE(PT_Float);
141+
RET_CASE(PT_Bool);
142+
RET_CASE(PT_Sint8);
143+
RET_CASE(PT_Uint8);
144+
RET_CASE(PT_Sint16);
145+
RET_CASE(PT_Uint16);
146+
RET_CASE(PT_Sint32);
147+
RET_CASE(PT_Uint32);
148+
RET_CASE(PT_Sint64);
149+
RET_CASE(PT_Uint64);
150+
default:
151+
llvm_unreachable("Unsupported return type for builtin function");
101152
}
102-
103-
llvm_unreachable("size_t isn't 64 or 32 bit?");
153+
#undef RET_CASE
104154
}
105155

106156
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
@@ -457,40 +507,55 @@ static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
457507
return true;
458508
}
459509

510+
static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
511+
const InterpFrame *Frame,
512+
const Function *Func,
513+
const CallExpr *Call) {
514+
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
515+
APSInt Val = peekToAPSInt(S.Stk, ArgT);
516+
pushAPSInt(S, APSInt(Val.reverseBits(), /*IsUnsigned=*/true));
517+
return true;
518+
}
519+
460520
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
461521
const CallExpr *Call) {
462522
InterpFrame *Frame = S.Current;
463523
APValue Dummy;
464524

525+
QualType ReturnType = Call->getCallReturnType(S.getCtx());
526+
std::optional<PrimType> ReturnT = S.getContext().classify(ReturnType);
527+
// If classify failed, we assume void.
528+
assert(ReturnT || ReturnType->isVoidType());
529+
465530
switch (F->getBuiltinID()) {
466531
case Builtin::BI__builtin_is_constant_evaluated:
467532
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
468-
return Ret<PT_Bool>(S, OpPC, Dummy);
533+
break;
469534
case Builtin::BI__builtin_assume:
470-
return RetVoid(S, OpPC, Dummy);
535+
break;
471536
case Builtin::BI__builtin_strcmp:
472-
if (interp__builtin_strcmp(S, OpPC, Frame))
473-
return retInt(S, OpPC, Dummy);
537+
if (!interp__builtin_strcmp(S, OpPC, Frame))
538+
return false;
474539
break;
475540
case Builtin::BI__builtin_strlen:
476-
if (interp__builtin_strlen(S, OpPC, Frame))
477-
return retSizeT(S, OpPC, Dummy);
541+
if (!interp__builtin_strlen(S, OpPC, Frame))
542+
return false;
478543
break;
479544
case Builtin::BI__builtin_nan:
480545
case Builtin::BI__builtin_nanf:
481546
case Builtin::BI__builtin_nanl:
482547
case Builtin::BI__builtin_nanf16:
483548
case Builtin::BI__builtin_nanf128:
484-
if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
485-
return Ret<PT_Float>(S, OpPC, Dummy);
549+
if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
550+
return false;
486551
break;
487552
case Builtin::BI__builtin_nans:
488553
case Builtin::BI__builtin_nansf:
489554
case Builtin::BI__builtin_nansl:
490555
case Builtin::BI__builtin_nansf16:
491556
case Builtin::BI__builtin_nansf128:
492-
if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
493-
return Ret<PT_Float>(S, OpPC, Dummy);
557+
if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
558+
return false;
494559
break;
495560

496561
case Builtin::BI__builtin_huge_val:
@@ -503,85 +568,85 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
503568
case Builtin::BI__builtin_infl:
504569
case Builtin::BI__builtin_inff16:
505570
case Builtin::BI__builtin_inff128:
506-
if (interp__builtin_inf(S, OpPC, Frame, F))
507-
return Ret<PT_Float>(S, OpPC, Dummy);
571+
if (!interp__builtin_inf(S, OpPC, Frame, F))
572+
return false;
508573
break;
509574
case Builtin::BI__builtin_copysign:
510575
case Builtin::BI__builtin_copysignf:
511576
case Builtin::BI__builtin_copysignl:
512577
case Builtin::BI__builtin_copysignf128:
513-
if (interp__builtin_copysign(S, OpPC, Frame, F))
514-
return Ret<PT_Float>(S, OpPC, Dummy);
578+
if (!interp__builtin_copysign(S, OpPC, Frame, F))
579+
return false;
515580
break;
516581

517582
case Builtin::BI__builtin_fmin:
518583
case Builtin::BI__builtin_fminf:
519584
case Builtin::BI__builtin_fminl:
520585
case Builtin::BI__builtin_fminf16:
521586
case Builtin::BI__builtin_fminf128:
522-
if (interp__builtin_fmin(S, OpPC, Frame, F))
523-
return Ret<PT_Float>(S, OpPC, Dummy);
587+
if (!interp__builtin_fmin(S, OpPC, Frame, F))
588+
return false;
524589
break;
525590

526591
case Builtin::BI__builtin_fmax:
527592
case Builtin::BI__builtin_fmaxf:
528593
case Builtin::BI__builtin_fmaxl:
529594
case Builtin::BI__builtin_fmaxf16:
530595
case Builtin::BI__builtin_fmaxf128:
531-
if (interp__builtin_fmax(S, OpPC, Frame, F))
532-
return Ret<PT_Float>(S, OpPC, Dummy);
596+
if (!interp__builtin_fmax(S, OpPC, Frame, F))
597+
return false;
533598
break;
534599

535600
case Builtin::BI__builtin_isnan:
536-
if (interp__builtin_isnan(S, OpPC, Frame, F))
537-
return retInt(S, OpPC, Dummy);
601+
if (!interp__builtin_isnan(S, OpPC, Frame, F))
602+
return false;
538603
break;
539604
case Builtin::BI__builtin_issignaling:
540-
if (interp__builtin_issignaling(S, OpPC, Frame, F))
541-
return retInt(S, OpPC, Dummy);
605+
if (!interp__builtin_issignaling(S, OpPC, Frame, F))
606+
return false;
542607
break;
543608

544609
case Builtin::BI__builtin_isinf:
545-
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
546-
return retInt(S, OpPC, Dummy);
610+
if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
611+
return false;
547612
break;
548613

549614
case Builtin::BI__builtin_isinf_sign:
550-
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
551-
return retInt(S, OpPC, Dummy);
615+
if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
616+
return false;
552617
break;
553618

554619
case Builtin::BI__builtin_isfinite:
555-
if (interp__builtin_isfinite(S, OpPC, Frame, F))
556-
return retInt(S, OpPC, Dummy);
620+
if (!interp__builtin_isfinite(S, OpPC, Frame, F))
621+
return false;
557622
break;
558623
case Builtin::BI__builtin_isnormal:
559-
if (interp__builtin_isnormal(S, OpPC, Frame, F))
560-
return retInt(S, OpPC, Dummy);
624+
if (!interp__builtin_isnormal(S, OpPC, Frame, F))
625+
return false;
561626
break;
562627
case Builtin::BI__builtin_issubnormal:
563-
if (interp__builtin_issubnormal(S, OpPC, Frame, F))
564-
return retInt(S, OpPC, Dummy);
628+
if (!interp__builtin_issubnormal(S, OpPC, Frame, F))
629+
return false;
565630
break;
566631
case Builtin::BI__builtin_iszero:
567-
if (interp__builtin_iszero(S, OpPC, Frame, F))
568-
return retInt(S, OpPC, Dummy);
632+
if (!interp__builtin_iszero(S, OpPC, Frame, F))
633+
return false;
569634
break;
570635
case Builtin::BI__builtin_isfpclass:
571-
if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
572-
return retInt(S, OpPC, Dummy);
636+
if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
637+
return false;
573638
break;
574639
case Builtin::BI__builtin_fpclassify:
575-
if (interp__builtin_fpclassify(S, OpPC, Frame, F))
576-
return retInt(S, OpPC, Dummy);
640+
if (!interp__builtin_fpclassify(S, OpPC, Frame, F))
641+
return false;
577642
break;
578643

579644
case Builtin::BI__builtin_fabs:
580645
case Builtin::BI__builtin_fabsf:
581646
case Builtin::BI__builtin_fabsl:
582647
case Builtin::BI__builtin_fabsf128:
583-
if (interp__builtin_fabs(S, OpPC, Frame, F))
584-
return Ret<PT_Float>(S, OpPC, Dummy);
648+
if (!interp__builtin_fabs(S, OpPC, Frame, F))
649+
return false;
585650
break;
586651

587652
case Builtin::BI__builtin_popcount:
@@ -590,29 +655,37 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
590655
case Builtin::BI__popcnt16: // Microsoft variants of popcount
591656
case Builtin::BI__popcnt:
592657
case Builtin::BI__popcnt64:
593-
if (interp__builtin_popcount(S, OpPC, Frame, F, Call))
594-
return retInt(S, OpPC, Dummy);
658+
if (!interp__builtin_popcount(S, OpPC, Frame, F, Call))
659+
return false;
595660
break;
596661

597662
case Builtin::BI__builtin_parity:
598663
case Builtin::BI__builtin_parityl:
599664
case Builtin::BI__builtin_parityll:
600-
if (interp__builtin_parity(S, OpPC, Frame, F, Call))
601-
return retInt(S, OpPC, Dummy);
665+
if (!interp__builtin_parity(S, OpPC, Frame, F, Call))
666+
return false;
602667
break;
603668

604669
case Builtin::BI__builtin_clrsb:
605670
case Builtin::BI__builtin_clrsbl:
606671
case Builtin::BI__builtin_clrsbll:
607-
if (interp__builtin_clrsb(S, OpPC, Frame, F, Call))
608-
return retInt(S, OpPC, Dummy);
672+
if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call))
673+
return false;
674+
break;
675+
676+
case Builtin::BI__builtin_bitreverse8:
677+
case Builtin::BI__builtin_bitreverse16:
678+
case Builtin::BI__builtin_bitreverse32:
679+
case Builtin::BI__builtin_bitreverse64:
680+
if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call))
681+
return false;
609682
break;
610683

611684
default:
612685
return false;
613686
}
614687

615-
return false;
688+
return retPrimValue(S, OpPC, Dummy, ReturnT);
616689
}
617690

618691
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,10 @@ namespace clrsb {
324324
char clrsb11[__builtin_clrsb(0xf) == BITSIZE(int) - 5 ? 1 : -1];
325325
char clrsb12[__builtin_clrsb(~0x1f) == BITSIZE(int) - 6 ? 1 : -1];
326326
}
327+
328+
namespace bitreverse {
329+
char bitreverse1[__builtin_bitreverse8(0x01) == 0x80 ? 1 : -1];
330+
char bitreverse2[__builtin_bitreverse16(0x3C48) == 0x123C ? 1 : -1];
331+
char bitreverse3[__builtin_bitreverse32(0x12345678) == 0x1E6A2C48 ? 1 : -1];
332+
char bitreverse4[__builtin_bitreverse64(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480 ? 1 : -1];
333+
}

0 commit comments

Comments
 (0)