@@ -16352,42 +16352,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1635216352 case Builtin::BI_rotr:
1635316353 case Builtin::BI_lrotr:
1635416354 case Builtin::BI_rotr64: {
16355- APSInt Val, Amt ;
16356- if (!EvaluateInteger(E->getArg(0), Val , Info) ||
16357- !EvaluateInteger(E->getArg(1), Amt , Info))
16355+ APSInt Value, Amount ;
16356+ if (!EvaluateInteger(E->getArg(0), Value , Info) ||
16357+ !EvaluateInteger(E->getArg(1), Amount , Info))
1635816358 return false;
1635916359
16360- // Normalize shift amount to [0, BitWidth) range to match runtime behavior
16361- unsigned BitWidth = Val.getBitWidth();
16362- unsigned AmtBitWidth = Amt.getBitWidth();
16363- if (BitWidth == 1) {
16364- // Rotating a 1-bit value is always a no-op
16365- Amt = APSInt(APInt(AmtBitWidth, 0), Amt.isUnsigned());
16366- } else {
16367- // Divisor is always unsigned to avoid misinterpreting BitWidth as
16368- // negative in small bit widths (e.g., BitWidth=2 would be -2 if signed).
16369- APSInt Divisor;
16370- if (AmtBitWidth > BitWidth) {
16371- Divisor =
16372- APSInt(llvm::APInt(AmtBitWidth, BitWidth), /*isUnsigned=*/true);
16373- } else {
16374- Divisor = APSInt(llvm::APInt(BitWidth, BitWidth), /*isUnsigned=*/true);
16375- if (AmtBitWidth < BitWidth) {
16376- Amt = Amt.extend(BitWidth);
16377- }
16378- }
16379-
16380- // Normalize to [0, BitWidth)
16381- if (Amt.isSigned()) {
16382- Amt = APSInt(Amt.srem(Divisor), /*isUnsigned=*/false);
16383- if (Amt.isNegative()) {
16384- APSInt SignedDivisor(Divisor, /*isUnsigned=*/false);
16385- Amt += SignedDivisor;
16386- }
16387- } else {
16388- Amt = APSInt(Amt.urem(Divisor), /*isUnsigned=*/true);
16389- }
16390- }
16360+ Amount = NormalizeRotateAmount(Value, Amount);
1639116361
1639216362 switch (BuiltinOp) {
1639316363 case Builtin::BI__builtin_rotateright8:
@@ -16400,9 +16370,11 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1640016370 case Builtin::BI_rotr:
1640116371 case Builtin::BI_lrotr:
1640216372 case Builtin::BI_rotr64:
16403- return Success(APSInt(Val.rotr(Amt.getZExtValue()), Val.isUnsigned()), E);
16373+ return Success(
16374+ APSInt(Value.rotr(Amount.getZExtValue()), Value.isUnsigned()), E);
1640416375 default:
16405- return Success(APSInt(Val.rotl(Amt.getZExtValue()), Val.isUnsigned()), E);
16376+ return Success(
16377+ APSInt(Value.rotl(Amount.getZExtValue()), Value.isUnsigned()), E);
1640616378 }
1640716379 }
1640816380
@@ -19781,6 +19753,42 @@ void HandleComplexComplexDiv(APFloat A, APFloat B, APFloat C, APFloat D,
1978119753 }
1978219754}
1978319755
19756+ APSInt NormalizeRotateAmount(const APSInt &Value, const APSInt &Amount) {
19757+ // Normalize shift amount to [0, BitWidth) range to match runtime behavior
19758+ APSInt NormAmt = Amount;
19759+ unsigned BitWidth = Value.getBitWidth();
19760+ unsigned AmtBitWidth = NormAmt.getBitWidth();
19761+ if (BitWidth == 1) {
19762+ // Rotating a 1-bit value is always a no-op
19763+ NormAmt = APSInt(APInt(AmtBitWidth, 0), NormAmt.isUnsigned());
19764+ } else {
19765+ // Divisor is always unsigned to avoid misinterpreting BitWidth as
19766+ // negative in small bit widths (e.g., BitWidth=2 would be -2 if signed).
19767+ APInt Divisor;
19768+ if (AmtBitWidth > BitWidth) {
19769+ Divisor = llvm::APInt(AmtBitWidth, BitWidth);
19770+ } else {
19771+ Divisor = llvm::APInt(BitWidth, BitWidth);
19772+ if (AmtBitWidth < BitWidth) {
19773+ NormAmt = NormAmt.extend(BitWidth);
19774+ }
19775+ }
19776+
19777+ // Normalize to [0, BitWidth)
19778+ if (NormAmt.isSigned()) {
19779+ NormAmt = APSInt(NormAmt.srem(Divisor), /*isUnsigned=*/false);
19780+ if (NormAmt.isNegative()) {
19781+ APSInt SignedDivisor(Divisor, /*isUnsigned=*/false);
19782+ NormAmt += SignedDivisor;
19783+ }
19784+ } else {
19785+ NormAmt = APSInt(NormAmt.urem(Divisor), /*isUnsigned=*/true);
19786+ }
19787+ }
19788+
19789+ return NormAmt;
19790+ }
19791+
1978419792bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1978519793 if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma)
1978619794 return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
0 commit comments