mirror of
https://github.com/cc65/cc65.git
synced 2025-01-03 16:33:19 +00:00
Fixed bitwise shift with numeric constant operand(s).
This commit is contained in:
parent
d006317b0e
commit
14988f5dda
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user