mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 17:29:50 +00:00
Fixed several more problems like the one in Assignment() some time ago: An
expression that yields a constant value may have side effects, and the expression code must not be removed in this case. git-svn-id: svn://svn.cc65.org/cc65/trunk@4138 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
2d3b0f1146
commit
e68332a10b
104
src/cc65/expr.c
104
src/cc65/expr.c
@ -828,7 +828,7 @@ static void ArrayRef (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TOS now contains ptr to array elements. Get the subscript. */
|
/* TOS now contains ptr to array elements. Get the subscript. */
|
||||||
ExprWithCheck (hie0, &Subscript);
|
MarkedExprWithCheck (hie0, &Subscript);
|
||||||
|
|
||||||
/* Check the types of array and subscript. We can either have a
|
/* Check the types of array and subscript. We can either have a
|
||||||
* pointer/array to the left, in which case the subscript must be of an
|
* pointer/array to the left, in which case the subscript must be of an
|
||||||
@ -870,7 +870,7 @@ static void ArrayRef (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the subscript is constant absolute value */
|
/* Check if the subscript is constant absolute value */
|
||||||
if (ED_IsConstAbs (&Subscript)) {
|
if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
|
||||||
|
|
||||||
/* The array subscript is a numeric constant. If we had pushed the
|
/* The array subscript is a numeric constant. If we had pushed the
|
||||||
* array base address onto the stack before, we can remove this value,
|
* array base address onto the stack before, we can remove this value,
|
||||||
@ -1896,7 +1896,14 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the right hand side */
|
/* Get the right hand side */
|
||||||
rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0);
|
MarkedExprWithCheck (hienext, &Expr2);
|
||||||
|
|
||||||
|
/* Check for a constant expression */
|
||||||
|
rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
|
||||||
|
if (!rconst) {
|
||||||
|
/* Not constant, load into the primary */
|
||||||
|
LoadExpr (CF_NONE, &Expr2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure, the types are compatible */
|
/* Make sure, the types are compatible */
|
||||||
if (IsClassInt (Expr->Type)) {
|
if (IsClassInt (Expr->Type)) {
|
||||||
@ -2064,21 +2071,21 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
|
|
||||||
/* Both expressions are constants. Check for pointer arithmetic */
|
/* Both expressions are constants. Check for pointer arithmetic */
|
||||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||||
/* Left is pointer, right is int, must scale rhs */
|
/* Left is pointer, right is int, must scale rhs */
|
||||||
Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst);
|
Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst);
|
||||||
/* Result type is a pointer */
|
/* Result type is a pointer */
|
||||||
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
||||||
/* Left is int, right is pointer, must scale lhs */
|
/* Left is int, right is pointer, must scale lhs */
|
||||||
Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal;
|
Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal;
|
||||||
/* Result type is a pointer */
|
/* Result type is a pointer */
|
||||||
Expr->Type = Expr2.Type;
|
Expr->Type = Expr2.Type;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer addition */
|
/* Integer addition */
|
||||||
Expr->IVal += Expr2.IVal;
|
Expr->IVal += Expr2.IVal;
|
||||||
typeadjust (Expr, &Expr2, 1);
|
typeadjust (Expr, &Expr2, 1);
|
||||||
} else {
|
} else {
|
||||||
/* OOPS */
|
/* OOPS */
|
||||||
Error ("Invalid operands for binary operator `+'");
|
Error ("Invalid operands for binary operator `+'");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -2176,7 +2183,10 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
g_push (TypeOf (Expr->Type), 0); /* --> stack */
|
g_push (TypeOf (Expr->Type), 0); /* --> stack */
|
||||||
|
|
||||||
/* Evaluate the rhs */
|
/* Evaluate the rhs */
|
||||||
if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
|
MarkedExprWithCheck (hie9, &Expr2);
|
||||||
|
|
||||||
|
/* Check for a constant rhs expression */
|
||||||
|
if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
|
||||||
|
|
||||||
/* Right hand side is a constant. Get the rhs type */
|
/* Right hand side is a constant. Get the rhs type */
|
||||||
rhst = Expr2.Type;
|
rhst = Expr2.Type;
|
||||||
@ -2210,6 +2220,9 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/* Not constant, load into the primary */
|
||||||
|
LoadExpr (CF_NONE, &Expr2);
|
||||||
|
|
||||||
/* lhs and rhs are not constant. Get the rhs type. */
|
/* lhs and rhs are not constant. Get the rhs type. */
|
||||||
rhst = Expr2.Type;
|
rhst = Expr2.Type;
|
||||||
|
|
||||||
@ -2289,7 +2302,10 @@ static void parsesub (ExprDesc* Expr)
|
|||||||
g_push (TypeOf (lhst), 0); /* --> stack */
|
g_push (TypeOf (lhst), 0); /* --> stack */
|
||||||
|
|
||||||
/* Parse the right hand side */
|
/* Parse the right hand side */
|
||||||
if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
|
MarkedExprWithCheck (hie9, &Expr2);
|
||||||
|
|
||||||
|
/* Check for a constant rhs expression */
|
||||||
|
if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
|
||||||
|
|
||||||
/* The right hand side is constant. Get the rhs type. */
|
/* The right hand side is constant. Get the rhs type. */
|
||||||
rhst = Expr2.Type;
|
rhst = Expr2.Type;
|
||||||
@ -2361,38 +2377,41 @@ static void parsesub (ExprDesc* Expr)
|
|||||||
/* Do the subtraction */
|
/* Do the subtraction */
|
||||||
g_dec (flags | CF_CONST, Expr2.IVal);
|
g_dec (flags | CF_CONST, Expr2.IVal);
|
||||||
|
|
||||||
/* If this was a pointer subtraction, we must scale the result */
|
/* If this was a pointer subtraction, we must scale the result */
|
||||||
if (rscale != 1) {
|
if (rscale != 1) {
|
||||||
g_scale (flags, -rscale);
|
g_scale (flags, -rscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Result is a rvalue in the primary register */
|
/* Result is a rvalue in the primary register */
|
||||||
ED_MakeRValExpr (Expr);
|
ED_MakeRValExpr (Expr);
|
||||||
ED_MarkAsUntested (Expr);
|
ED_MarkAsUntested (Expr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Right hand side is not constant. Get the rhs type. */
|
/* Not constant, load into the primary */
|
||||||
rhst = Expr2.Type;
|
LoadExpr (CF_NONE, &Expr2);
|
||||||
|
|
||||||
|
/* Right hand side is not constant. Get the rhs type. */
|
||||||
|
rhst = Expr2.Type;
|
||||||
|
|
||||||
/* Check for pointer arithmetic */
|
/* Check for pointer arithmetic */
|
||||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||||
/* Left is pointer, right is int, must scale rhs */
|
/* Left is pointer, right is int, must scale rhs */
|
||||||
g_scale (CF_INT, CheckedPSizeOf (lhst));
|
g_scale (CF_INT, CheckedPSizeOf (lhst));
|
||||||
/* Operate on pointers, result type is a pointer */
|
/* Operate on pointers, result type is a pointer */
|
||||||
flags = CF_PTR;
|
flags = CF_PTR;
|
||||||
} else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
|
} else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
|
||||||
/* Left is pointer, right is pointer, must scale result */
|
/* Left is pointer, right is pointer, must scale result */
|
||||||
if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
|
if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
|
||||||
Error ("Incompatible pointer types");
|
Error ("Incompatible pointer types");
|
||||||
} else {
|
} else {
|
||||||
rscale = CheckedPSizeOf (lhst);
|
rscale = CheckedPSizeOf (lhst);
|
||||||
}
|
}
|
||||||
/* Operate on pointers, result type is an integer */
|
/* Operate on pointers, result type is an integer */
|
||||||
flags = CF_PTR;
|
flags = CF_PTR;
|
||||||
Expr->Type = type_int;
|
Expr->Type = type_int;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer subtraction. If the left hand side descriptor says that
|
/* Integer subtraction. If the left hand side descriptor says that
|
||||||
* the lhs is const, we have to remove this mark, since this is no
|
* the lhs is const, we have to remove this mark, since this is no
|
||||||
@ -2868,7 +2887,10 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr)
|
|||||||
g_push (flags, 0);
|
g_push (flags, 0);
|
||||||
|
|
||||||
/* Evaluate the rhs */
|
/* Evaluate the rhs */
|
||||||
if (evalexpr (CF_NONE, hie1, &Expr2) == 0) {
|
MarkedExprWithCheck (hie1, &Expr2);
|
||||||
|
|
||||||
|
/* Check for a constant expression */
|
||||||
|
if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
|
||||||
/* The resulting value is a constant. If the generator has the NOPUSH
|
/* The resulting value is a constant. If the generator has the NOPUSH
|
||||||
* flag set, don't push the lhs.
|
* flag set, don't push the lhs.
|
||||||
*/
|
*/
|
||||||
@ -2904,7 +2926,9 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr)
|
|||||||
Gen->Func (flags | CF_CONST, Expr2.IVal);
|
Gen->Func (flags | CF_CONST, Expr2.IVal);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* rhs is not constant and already in the primary register */
|
|
||||||
|
/* rhs is not constant. Load into the primary */
|
||||||
|
LoadExpr (CF_NONE, &Expr2);
|
||||||
if (MustScale) {
|
if (MustScale) {
|
||||||
/* lhs is a pointer, scale rhs */
|
/* lhs is a pointer, scale rhs */
|
||||||
g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1));
|
g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1));
|
||||||
|
@ -154,7 +154,7 @@ static void ParseArg (ArgDesc* Arg, Type* Type)
|
|||||||
GetCodePos (&Arg->Start);
|
GetCodePos (&Arg->Start);
|
||||||
|
|
||||||
/* Read the expression we're going to pass to the function */
|
/* Read the expression we're going to pass to the function */
|
||||||
ExprWithCheck (hie1, &Arg->Expr);
|
MarkedExprWithCheck (hie1, &Arg->Expr);
|
||||||
|
|
||||||
/* Remember the actual argument type */
|
/* Remember the actual argument type */
|
||||||
Arg->Type = Arg->Expr.Type;
|
Arg->Type = Arg->Expr.Type;
|
||||||
@ -165,7 +165,7 @@ static void ParseArg (ArgDesc* Arg, Type* Type)
|
|||||||
/* If the value is a constant, set the flag, otherwise load it into the
|
/* If the value is a constant, set the flag, otherwise load it into the
|
||||||
* primary register.
|
* primary register.
|
||||||
*/
|
*/
|
||||||
if (ED_IsConstAbsInt (&Arg->Expr)) {
|
if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) {
|
||||||
/* Remember that we have a constant value */
|
/* Remember that we have a constant value */
|
||||||
Arg->Flags |= CF_CONST;
|
Arg->Flags |= CF_CONST;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user