Skip to content
57 changes: 17 additions & 40 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,30 +678,6 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
APSInt Val = popToAPSInt(S, Call->getArg(0));
pushInteger(S, Val.popcount() % 2, Call->getType());
return true;
}

static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
APSInt Val = popToAPSInt(S, Call->getArg(0));
pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
return true;
}

static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
APSInt Val = popToAPSInt(S, Call->getArg(0));
pushInteger(S, Val.reverseBits(), Call->getType());
return true;
}

static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
Expand Down Expand Up @@ -736,16 +712,6 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
APSInt Value = popToAPSInt(S, Call->getArg(0));

uint64_t N = Value.countr_zero();
pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
return true;
}

static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
Expand Down Expand Up @@ -3158,18 +3124,25 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_parity:
case Builtin::BI__builtin_parityl:
case Builtin::BI__builtin_parityll:
return interp__builtin_parity(S, OpPC, Frame, Call);

return interp__builtin_elementwise_int_unaryop(
S, OpPC, Call, [](const APSInt &Val) -> APInt {
return APInt(Val.getBitWidth(), Val.popcount() % 2);
});
case Builtin::BI__builtin_clrsb:
case Builtin::BI__builtin_clrsbl:
case Builtin::BI__builtin_clrsbll:
return interp__builtin_clrsb(S, OpPC, Frame, Call);

return interp__builtin_elementwise_int_unaryop(
S, OpPC, Call, [](const APSInt &Val) -> APInt {
return APInt(Val.getBitWidth(),
Val.getBitWidth() - Val.getSignificantBits());
});
case Builtin::BI__builtin_bitreverse8:
case Builtin::BI__builtin_bitreverse16:
case Builtin::BI__builtin_bitreverse32:
case Builtin::BI__builtin_bitreverse64:
return interp__builtin_bitreverse(S, OpPC, Frame, Call);
return interp__builtin_elementwise_int_unaryop(
S, OpPC, Call,
[](const APSInt &Val) -> APInt { return Val.reverseBits(); });

case Builtin::BI__builtin_classify_type:
return interp__builtin_classify_type(S, OpPC, Frame, Call);
Expand Down Expand Up @@ -3209,7 +3182,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_ffs:
case Builtin::BI__builtin_ffsl:
case Builtin::BI__builtin_ffsll:
return interp__builtin_ffs(S, OpPC, Frame, Call);
return interp__builtin_elementwise_int_unaryop(
S, OpPC, Call, [](const APSInt &Val) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, you only left off the trailing return type on this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed it on my commit. This should be fixed, thank you for pointing it out. I can get it fixed with my next PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shafik It doesn't look like any of the interp__builtin_elementwise_int_unaryop calls require a trailing type - why do you want it adding here instead of stripping it off the others?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My assumption was that in the Val.reverseBits() case it was not obvious and it was added to the others for uniformity and the fourth was accidently left out. The PR was accepted so this felt like a valid take. I would also be consistent if you removed it from all of them.

@tbaederr how do you feel?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually add a trailing return type when I write lambdas, but I think that's the exception when looking at the entire code base, so I don't mind either way.

Copy link
Contributor Author

@donneypr donneypr Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my novice 2 cents: If we're keeping the trailing return type for some of the functions eg. Val.reverseBits(), I think it would better to add it to all of them for uniformity. I wasn't going to add it initially but a previous PR had the trailing type so I used it to stay consistent.

return APInt(Val.getBitWidth(),
Val.isZero() ? 0u : Val.countTrailingZeros() + 1u);
});

case Builtin::BIaddressof:
case Builtin::BI__addressof:
Expand Down