1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 00:29:31 +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 committed by mrdudz
parent fcbb4a5246
commit 4cb5063e9c
7 changed files with 119 additions and 11 deletions

View File

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

View File

@ -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);
}
}
}
@ -4134,22 +4192,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

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

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