mirror of
https://github.com/cc65/cc65.git
synced 2024-12-24 11:31:31 +00:00
Merge pull request #1785 from acqn/Effectless
[cc65] Avoid generating asm from C code that has no observable effects
This commit is contained in:
commit
6b0afe0834
@ -590,6 +590,12 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
|
||||
/* Normal straight 'op=' */
|
||||
OpAssignArithmetic (Gen, Expr, Op);
|
||||
}
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
@ -710,4 +716,10 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
||||
|
||||
/* Expression is an rvalue in the primary now */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
@ -642,6 +642,9 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr)
|
||||
/* Sufficient to pop the processor flags */
|
||||
AddCodeLine ("plp");
|
||||
}
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
@ -816,6 +819,9 @@ static unsigned FunctionArgList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (ED, &Expr);
|
||||
|
||||
/* Check for end of argument list */
|
||||
if (CurTok.Tok != TOK_COMMA) {
|
||||
break;
|
||||
@ -1058,6 +1064,9 @@ static void FunctionCall (ExprDesc* Expr)
|
||||
}
|
||||
|
||||
Expr->Type = ReturnType;
|
||||
|
||||
/* We assume all function calls had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
@ -1267,7 +1276,7 @@ static void Primary (ExprDesc* E)
|
||||
case TOK_ASM:
|
||||
/* ASM statement */
|
||||
AsmStatement ();
|
||||
E->Flags = E_RTYPE_RVAL | E_EVAL_MAYBE_UNUSED;
|
||||
E->Flags = E_RTYPE_RVAL | E_EVAL_MAYBE_UNUSED | E_SIDE_EFFECTS;
|
||||
E->Type = type_void;
|
||||
break;
|
||||
|
||||
@ -1652,6 +1661,9 @@ static void PreInc (ExprDesc* Expr)
|
||||
|
||||
/* Result is an expression, no reference */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
@ -1679,6 +1691,9 @@ static void PreDec (ExprDesc* Expr)
|
||||
|
||||
/* Result is an expression, no reference */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
@ -1715,6 +1730,9 @@ static void PostInc (ExprDesc* Expr)
|
||||
LoadExpr (CF_NONE, Expr);
|
||||
AddCodeLine ("inc %s", ED_GetLabelName (Expr, 0));
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
if (ED_IsLocPrimaryOrExpr (Expr)) {
|
||||
@ -1722,6 +1740,9 @@ static void PostInc (ExprDesc* Expr)
|
||||
/* Do the increment */
|
||||
DoInc (Expr, OA_NEED_OLD);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
/* Defer the increment until after the value of this expression is used */
|
||||
@ -1765,6 +1786,9 @@ static void PostDec (ExprDesc* Expr)
|
||||
LoadExpr (CF_NONE, Expr);
|
||||
AddCodeLine ("dec %s", ED_GetLabelName (Expr, 0));
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
if (ED_IsLocPrimaryOrExpr (Expr)) {
|
||||
@ -1772,6 +1796,9 @@ static void PostDec (ExprDesc* Expr)
|
||||
/* Do the decrement */
|
||||
DoDec (Expr, OA_NEED_OLD);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
/* Defer the decrement until after the value of this expression is used */
|
||||
@ -2232,6 +2259,9 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
|
||||
/* We have an rvalue in the primary now */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2653,6 +2683,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
||||
|
||||
/* Result type is always boolean */
|
||||
Done: Expr->Type = type_bool;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3069,6 +3102,9 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef)
|
||||
|
||||
/* Condition code not set */
|
||||
ED_MarkAsUntested (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
@ -3346,6 +3382,9 @@ static void parsesub (ExprDesc* Expr)
|
||||
|
||||
/* Condition code not set */
|
||||
ED_MarkAsUntested (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
@ -3597,6 +3636,12 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr->Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Last expression */
|
||||
@ -3762,6 +3807,11 @@ static void hieOr (ExprDesc *Expr)
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr->Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Convert to bool */
|
||||
@ -4053,6 +4103,14 @@ static void hieQuest (ExprDesc* Expr)
|
||||
|
||||
/* Setup the target expression */
|
||||
Expr->Type = ResultType;
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr2.Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
if ((Expr3.Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4130,26 +4188,39 @@ void hie0 (ExprDesc *Expr)
|
||||
/* Append deferred inc/dec at sequence point */
|
||||
DoDeferred (SQP_KEEP_NONE, Expr);
|
||||
|
||||
/* If the expression didn't generate code or isn't cast to type void,
|
||||
** emit a warning.
|
||||
/* If the expression has no observable effect and isn't cast to type
|
||||
** void, emit a warning and remove useless code if any.
|
||||
*/
|
||||
GetCodePos (&End);
|
||||
if (CodeRangeIsEmpty (&Start, &End) ||
|
||||
(Expr->Flags & E_SIDE_EFFECTS) == 0) {
|
||||
|
||||
if (!ED_MayHaveNoEffect (Expr) &&
|
||||
CodeRangeIsEmpty (&Start, &End) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Expression result unused");
|
||||
Warning ("Left-hand operand of comma expression has no effect");
|
||||
}
|
||||
|
||||
/* Remove code with no effect */
|
||||
RemoveCode (&Start);
|
||||
}
|
||||
|
||||
PrevErrorCount = ErrorCount;
|
||||
|
||||
/* Remember the current code position */
|
||||
GetCodePos (&Start);
|
||||
|
||||
/* Keep viral flags propagated from subexpressions */
|
||||
Flags |= Expr->Flags & E_MASK_VIRAL;
|
||||
|
||||
/* Reset the expression */
|
||||
ED_Init (Expr);
|
||||
Expr->Flags = Flags;
|
||||
Expr->Flags = Flags & ~E_MASK_VIRAL;
|
||||
NextToken ();
|
||||
hie1 (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
Expr->Flags |= Flags & E_MASK_VIRAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,7 @@ enum {
|
||||
E_LOADED = 0x1000, /* Expression is loaded in primary */
|
||||
E_CC_SET = 0x2000, /* Condition codes are set */
|
||||
E_HAVE_MARKS = 0x4000, /* Code marks are valid */
|
||||
E_SIDE_EFFECTS = 0x8000, /* Expression has had side effects */
|
||||
|
||||
/* Optimization hints */
|
||||
E_MASK_NEED = 0x030000,
|
||||
@ -181,6 +182,9 @@ enum {
|
||||
/* Expression result must be known to the compiler and generate no code to load */
|
||||
E_EVAL_C_CONST = E_EVAL_COMPILER_KNOWN | E_EVAL_NO_CODE,
|
||||
|
||||
/* Flags to combine from subexpressions */
|
||||
E_MASK_VIRAL = E_SIDE_EFFECTS,
|
||||
|
||||
/* Flags to keep in subexpressions of most operations other than ternary */
|
||||
E_MASK_KEEP_SUBEXPR = E_MASK_EVAL,
|
||||
|
||||
@ -467,6 +471,16 @@ INLINE int ED_MayHaveNoEffect (const ExprDesc* Expr)
|
||||
# define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
|
||||
/* Propagate viral flags from subexpression */
|
||||
{
|
||||
Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL;
|
||||
}
|
||||
#else
|
||||
# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
||||
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
|
||||
|
@ -278,4 +278,8 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
||||
}
|
||||
}
|
||||
|
||||
if (ED_IsLVal (Expr) && IsQualVolatile (Expr->Type)) {
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
}
|
||||
|
@ -237,5 +237,8 @@ MakeRVal:
|
||||
|
||||
/* Set the type of the result */
|
||||
Expr->Type = ResultType;
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Expr2.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +185,9 @@ static void ParseArg (ArgDesc* Arg, const Type* Type, ExprDesc* Expr)
|
||||
|
||||
/* Use the type of the argument for the push */
|
||||
Arg->Flags |= TypeOf (Arg->Expr.Type);
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Arg->Expr.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
|
||||
|
||||
@ -1365,6 +1368,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
||||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
ConsumeRParen ();
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Arg.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
|
||||
|
||||
@ -1405,4 +1411,7 @@ void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval)
|
||||
|
||||
/* Call the handler function */
|
||||
D->Handler (F, lval);
|
||||
|
||||
/* We assume all function calls had side effects */
|
||||
lval->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
@ -609,17 +609,23 @@ static void Statement (int* PendingToken)
|
||||
Expr.Flags |= E_NEED_NONE;
|
||||
Expression0 (&Expr);
|
||||
|
||||
/* If the statement didn't generate code, and is not of type
|
||||
** void, emit a warning.
|
||||
/* If the statement has no observable effect and isn't cast to type
|
||||
** void, emit a warning and remove useless code if any.
|
||||
*/
|
||||
GetCodePos (&End);
|
||||
if (!ED_YetToLoad (&Expr) &&
|
||||
!ED_MayHaveNoEffect (&Expr) &&
|
||||
CodeRangeIsEmpty (&Start, &End) &&
|
||||
if (CodeRangeIsEmpty (&Start, &End) ||
|
||||
(Expr.Flags & E_SIDE_EFFECTS) == 0) {
|
||||
|
||||
if (!ED_MayHaveNoEffect (&Expr) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Expression result unused");
|
||||
Warning ("Statement has no effect");
|
||||
}
|
||||
|
||||
/* Remove code with no effect */
|
||||
RemoveCode (&Start);
|
||||
}
|
||||
|
||||
CheckSemi (PendingToken);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user