1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 07:29:33 +00:00

Now the compiler tracks code that has no observable effect.

This commit is contained in:
acqn 2021-02-21 16:36:29 +08:00
parent e95db437a9
commit 7f05bd797f
7 changed files with 119 additions and 11 deletions

View File

@ -605,6 +605,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);
}
@ -725,4 +731,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);
}

View File

@ -649,6 +649,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;
}
@ -822,6 +825,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;
@ -1064,6 +1070,9 @@ static void FunctionCall (ExprDesc* Expr)
}
Expr->Type = ReturnType;
/* We assume all function calls had side effects */
Expr->Flags |= E_SIDE_EFFECTS;
}
@ -1273,7 +1282,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;
@ -1658,6 +1667,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;
}
@ -1685,6 +1697,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;
}
@ -1721,6 +1736,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)) {
@ -1728,6 +1746,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 */
@ -1771,6 +1792,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)) {
@ -1778,6 +1802,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 */
@ -2238,6 +2265,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);
}
}
@ -2659,6 +2689,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);
}
}
@ -3075,6 +3108,9 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef)
/* Condition code not set */
ED_MarkAsUntested (Expr);
/* Propagate viral flags */
ED_PropagateFrom (Expr, &Expr2);
}
@ -3352,6 +3388,9 @@ static void parsesub (ExprDesc* Expr)
/* Condition code not set */
ED_MarkAsUntested (Expr);
/* Propagate viral flags */
ED_PropagateFrom (Expr, &Expr2);
}
@ -3603,6 +3642,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 */
@ -3768,6 +3813,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 */
@ -4059,6 +4109,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);
}
}
}
@ -4140,22 +4198,29 @@ void hie0 (ExprDesc *Expr)
** emit a warning.
*/
GetCodePos (&End);
if (!ED_MayHaveNoEffect (Expr) &&
CodeRangeIsEmpty (&Start, &End) &&
IS_Get (&WarnNoEffect) &&
if (!ED_MayHaveNoEffect (Expr) &&
(CodeRangeIsEmpty (&Start, &End) ||
(Expr->Flags & E_SIDE_EFFECTS) == 0) &&
IS_Get (&WarnNoEffect) &&
PrevErrorCount == ErrorCount) {
Warning ("Expression result unused");
Warning ("Left-hand operand of comma expression has no effect");
}
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;
}
}

View File

@ -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 */

View File

@ -277,4 +277,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;
}
}

View File

@ -237,5 +237,8 @@ MakeRVal:
/* Set the type of the result */
Expr->Type = ResultType;
/* Propagate from subexpressions */
Expr->Flags |= Expr2.Flags & E_MASK_VIRAL;
}
}

View File

@ -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;
}

View File

@ -613,12 +613,13 @@ static void Statement (int* PendingToken)
** void, emit a warning.
*/
GetCodePos (&End);
if (!ED_YetToLoad (&Expr) &&
!ED_MayHaveNoEffect (&Expr) &&
CodeRangeIsEmpty (&Start, &End) &&
IS_Get (&WarnNoEffect) &&
if (!ED_YetToLoad (&Expr) &&
!ED_MayHaveNoEffect (&Expr) &&
(CodeRangeIsEmpty (&Start, &End) ||
(Expr.Flags & E_SIDE_EFFECTS) == 0) &&
IS_Get (&WarnNoEffect) &&
PrevErrorCount == ErrorCount) {
Warning ("Expression result unused");
Warning ("Statement has no effect");
}
CheckSemi (PendingToken);
}