diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c index 168574a1b..f7385ace1 100644 --- a/src/cc65/shiftexpr.c +++ b/src/cc65/shiftexpr.c @@ -64,11 +64,11 @@ void ShiftExpr (struct ExprDesc* Expr) CodeMark Mark1; CodeMark Mark2; token_t Tok; /* The operator token */ - const Type* EffType; /* Effective lhs type */ const Type* ResultType; /* Type of the result */ unsigned ExprBits; /* Bits of the lhs operand */ unsigned GenFlags; /* Generator flags */ unsigned ltype; + int lconst; /* Operand is a constant */ int rconst; /* Operand is a constant */ @@ -92,7 +92,7 @@ void ShiftExpr (struct ExprDesc* Expr) NextToken (); /* Get the type of the result */ - ResultType = EffType = IntPromotion (Expr->Type); + ResultType = IntPromotion (Expr->Type); /* Prepare the code generator flags */ GenFlags = TypeOf (ResultType); @@ -103,7 +103,8 @@ void ShiftExpr (struct ExprDesc* Expr) /* Get the lhs on stack */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); - if (ED_IsConstAbs (Expr)) { + lconst = ED_IsConstAbs (Expr); + if (lconst) { /* Constant value */ GetCodePos (&Mark2); g_push (ltype | CF_CONST, Expr->IVal); @@ -115,7 +116,7 @@ void ShiftExpr (struct ExprDesc* Expr) } /* Get the right hand side */ - ExprWithCheck (hie8, &Expr2); + MarkedExprWithCheck (hie8, &Expr2); /* Check the type of the rhs */ if (!IsClassInt (Expr2.Type)) { @@ -124,7 +125,7 @@ void ShiftExpr (struct ExprDesc* Expr) } /* Check for a constant right side expression */ - rconst = ED_IsConstAbs (&Expr2); + rconst = ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2); if (!rconst) { /* Not constant, load into the primary */ @@ -154,31 +155,32 @@ void ShiftExpr (struct ExprDesc* Expr) } - /* If the shift count is zero, nothing happens */ - if (Expr2.IVal == 0) { + /* If the shift count is zero, nothing happens. If the left hand + ** side is a constant, the result is constant. + */ + if (Expr2.IVal == 0 || lconst) { - /* Result is already in Expr, remove the generated code */ - RemoveCode (&Mark1); + /* Set the type */ + Expr->Type = ResultType; - /* Done */ - goto Next; - } + if (lconst) { - /* If the left hand side is a constant, the result is constant */ - if (ED_IsConstAbs (Expr)) { + /* Evaluate the result */ + switch (Tok) { + case TOK_SHL: Expr->IVal <<= Expr2.IVal; break; + case TOK_SHR: Expr->IVal >>= Expr2.IVal; break; + default: /* Shutup gcc */ break; + } - /* Evaluate the result */ - switch (Tok) { - case TOK_SHL: Expr->IVal <<= Expr2.IVal; break; - case TOK_SHR: Expr->IVal >>= Expr2.IVal; break; - default: /* Shutup gcc */ break; + /* Limit the calculated value to the range of its type */ + LimitExprValue (Expr); } - /* Both operands are constant, remove the generated code */ + /* Result is already got, remove the generated code */ RemoveCode (&Mark1); /* Done */ - goto Next; + continue; } /* If we're shifting an integer or unsigned to the right, the lhs @@ -188,13 +190,12 @@ void ShiftExpr (struct ExprDesc* Expr) ** shift count is zero, we're done. */ if (Tok == TOK_SHR && - IsTypeInt (Expr->Type) && + IsClassInt (Expr->Type) && + SizeOf (Expr->Type) == SIZEOF_INT && ED_IsLVal (Expr) && ED_IsLocQuasiConst (Expr) && Expr2.IVal >= 8) { - const Type* OldType; - /* Increase the address by one and decrease the shift count */ ++Expr->IVal; Expr2.IVal -= 8; @@ -202,7 +203,6 @@ void ShiftExpr (struct ExprDesc* Expr) /* Replace the type of the expression temporarily by the ** corresponding char type. */ - OldType = Expr->Type; if (IsSignUnsigned (Expr->Type)) { Expr->Type = type_uchar; } else { @@ -215,9 +215,6 @@ void ShiftExpr (struct ExprDesc* Expr) /* Generate again code for the load, this time with the new type */ LoadExpr (CF_NONE, Expr); - /* Reset the type */ - Expr->Type = OldType; - /* If the shift count is now zero, we're done */ if (Expr2.IVal == 0) { /* Be sure to mark the value as in the primary */ @@ -238,7 +235,6 @@ MakeRVal: /* We have an rvalue in the primary now */ ED_FinalizeRValLoad (Expr); -Next: /* Set the type of the result */ Expr->Type = ResultType; }