1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-19 06:31:31 +00:00

Changed codegen for postfix inc/dec operations by deferring them till sequence points.

This usually allows faster & smaller code.
Note that deferred operations must still be called at sequence points even if the whole expressions containing them had constant values.
This commit is contained in:
acqn 2020-04-16 17:19:16 +08:00 committed by Oliver Schmidt
parent bb7b69f513
commit 5c43d1e04f
9 changed files with 526 additions and 58 deletions

View File

@ -320,6 +320,9 @@ static void Parse (void)
} else {
/* Parse the function body */
NewFunc (Entry, FuncDef);
/* Make sure we aren't omitting any work */
CheckDeferredOpAllDone ();
}
}
@ -395,6 +398,8 @@ void Compile (const char* FileName)
/* DefineNumericMacro ("__STDC__", 1); <- not now */
DefineNumericMacro ("__STDC_HOSTED__", 1);
InitDeferredOps ();
/* Create the base lexical level */
EnterGlobalLevel ();
@ -486,6 +491,8 @@ void Compile (const char* FileName)
}
}
DoneDeferredOps ();
if (Debug) {
PrintMacroStats (stdout);
}

View File

@ -2302,6 +2302,9 @@ static unsigned ParseScalarInit (Type* T)
/* Output the data */
DefineData (&ED);
/* Do this anyways for safety */
DoDeferred (SQP_KEEP_NONE, &ED);
/* Done */
return SizeOf (T);
}
@ -2321,6 +2324,9 @@ static unsigned ParsePointerInit (Type* T)
/* Output the data */
DefineData (&ED);
/* Do this anyways for safety */
DoDeferred (SQP_KEEP_NONE, &ED);
/* Close eventually opening braces */
ClosingCurlyBraces (BraceCount);

View File

@ -332,6 +332,264 @@ static void WarnConstCompareResult (const ExprDesc* Expr)
typedef enum {
DOT_INC,
DOT_DEC,
} DeferredOpType;
typedef struct {
ExprDesc Expr;
DeferredOpType OpType;
} DeferredOp;
Collection DeferredOps;
void InitDeferredOps (void)
/* Init the collection for storing deferred ops */
{
InitCollection (&DeferredOps);
}
void DoneDeferredOps (void)
/* Deinit the collection for storing deferred ops */
{
DoneCollection (&DeferredOps);
}
static void DeferInc (const ExprDesc* Expr)
/* Defer the post-inc and put it in a queue */
{
DeferredOp* Op = xmalloc (sizeof (DeferredOp));
memcpy (&Op->Expr, Expr, sizeof (ExprDesc));
Op->OpType = DOT_INC;
CollAppend (&DeferredOps, Op);
}
static void DeferDec (const ExprDesc* Expr)
/* Defer the post-dec and put it in a queue */
{
DeferredOp* Op = xmalloc (sizeof (DeferredOp));
memcpy (&Op->Expr, Expr, sizeof (ExprDesc));
Op->OpType = DOT_DEC;
CollAppend (&DeferredOps, Op);
}
static void DeferredInc (ExprDesc* Expr)
/* Do the deferred post-inc */
{
unsigned Flags;
unsigned long Val;
/* Get the flags */
Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST | CF_NOKEEP;
/* Get the increment value in bytes */
Val = IsTypePtr (Expr->Type) ? CheckedSizeOf (Expr->Type + 1) : 1;
/* Check the location of the data */
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
g_addeqstatic (Flags, Expr->IVal, 0, Val);
break;
case E_LOC_GLOBAL:
/* Global variable */
g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_STATIC:
case E_LOC_LITERAL:
/* Static variable or literal in the literal pool */
g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_REGISTER:
/* Register variable */
g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_STACK:
/* Value on the stack */
g_addeqlocal (Flags, Expr->IVal, Val);
break;
case E_LOC_PRIMARY:
/* The primary register */
g_inc (Flags, Val);
break;
case E_LOC_EXPR:
/* An expression in the primary register */
g_addeqind (Flags, Expr->IVal, Val);
break;
default:
Internal ("Invalid location in DeferredInc(): 0x%04X", ED_GetLoc (Expr));
}
}
static void DeferredDec (ExprDesc* Expr)
/* Do the deferred post-dec */
{
unsigned Flags;
unsigned long Val;
/* Get the flags */
Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST | CF_NOKEEP;
/* Get the increment value in bytes */
Val = IsTypePtr (Expr->Type) ? CheckedSizeOf (Expr->Type + 1) : 1;
/* Check the location of the data */
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
g_subeqstatic (Flags, Expr->IVal, 0, Val);
break;
case E_LOC_GLOBAL:
/* Global variable */
g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_STATIC:
case E_LOC_LITERAL:
/* Static variable or literal in the literal pool */
g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_REGISTER:
/* Register variable */
g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val);
break;
case E_LOC_STACK:
/* Value on the stack */
g_subeqlocal (Flags, Expr->IVal, Val);
break;
case E_LOC_PRIMARY:
/* The primary register */
g_dec (Flags, Val);
break;
case E_LOC_EXPR:
/* An expression in the primary register */
g_subeqind (Flags, Expr->IVal, Val);
break;
default:
Internal ("Invalid location in DeferredDec(): 0x%04X", ED_GetLoc (Expr));
}
}
int GetDeferredOpCount (void)
/* Return how many deferred operations are still waiting in the queque */
{
return (int)CollCount (&DeferredOps);
}
void CheckDeferredOpAllDone (void)
/* Check if all deferred operations are done at sequence points.
** Die off if check fails.
*/
{
if (GetDeferredOpCount () > 0) {
Internal ("Code generation messed up: missing operations past sequence points.");
}
}
void DoDeferred (unsigned Flags, ExprDesc* Expr)
/* Do deferred operations such as post-inc/dec at sequence points */
{
int I;
unsigned Size = 0;
int Count = GetDeferredOpCount ();
/* Nothing to be done */
if (Count <= 0) {
return;
}
/* Backup some regs/processor flags around the inc/dec */
if ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr)) {
/* Sufficient to add a pair of PHP/PLP for all cases */
AddCodeLine ("php");
}
/* Backup the content of EAX around the inc/dec */
if ((Flags & SQP_KEEP_EAX) != 0 && ED_NeedsPrimary (Expr)) {
/* Get the size */
Size = CheckedSizeOf (Expr->Type);
if (Size < 2) {
AddCodeLine ("pha");
} else if (Size < 3) {
AddCodeLine ("sta regsave");
AddCodeLine ("stx regsave+1");
} else {
AddCodeLine ("jsr saveeax");
}
}
for (I = 0; I < Count; ++I) {
DeferredOp* Op = CollAtUnchecked (&DeferredOps, I);
switch (Op->OpType) {
case DOT_INC:
DeferredInc (&Op->Expr);
break;
case DOT_DEC:
DeferredDec (&Op->Expr);
break;
}
xfree (&Op->Expr);
}
CollDeleteAll (&DeferredOps);
/* Restore the content of EAX around the inc/dec */
if ((Flags & SQP_KEEP_EAX) != 0 && ED_NeedsPrimary (Expr)) {
if (Size < 2) {
AddCodeLine ("pla");
} else if (Size < 3) {
AddCodeLine ("lda regsave");
AddCodeLine ("ldx regsave+1");
} else {
AddCodeLine ("jsr resteax");
}
}
/* Restore the regs/processor flags around the inc/dec */
if ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr)) {
/* Sufficient to pop the processor flags */
AddCodeLine ("plp");
}
}
static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
/* Parse a function parameter list, and pass the arguments to the called
** function. Depending on several criteria, this may be done by just pushing
@ -388,11 +646,17 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
}
}
/* The info of the last argument could be needed out of the loop */
ExprDesc Expr;
ED_Init (&Expr);
Expr.Flags |= ED->Flags & E_MASK_KEEP_SUBEXPR;
/* Parse the actual argument list */
while (CurTok.Tok != TOK_RPAREN) {
unsigned Flags; /* Code generator flags, not expression flags */
ExprDesc Expr;
/* This way the info of the last parameter won't be cleared */
ED_Init (&Expr);
Expr.Flags |= ED->Flags & E_MASK_KEEP_SUBEXPR;
@ -514,6 +778,11 @@ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
Error ("Too few arguments in function call");
}
/* Append deferred inc/dec before the function is called.
** The last parameter needs to be restored if it is passed with AX/EAX Regs.
*/
DoDeferred (IsFastcall ? SQP_KEEP_EAX : SQP_KEEP_NONE, &Expr);
/* The function returns the size of all arguments pushed onto the stack.
** However, if there are parameters missed (which is an error, and was
** flagged by the compiler), AND a stack frame was preallocated above,
@ -1728,7 +1997,7 @@ static void PreDec (ExprDesc* Expr)
static void PostInc (ExprDesc* Expr)
/* Handle the postincrement operator */
{
unsigned Flags;
unsigned Flags, Loc;
NextToken ();
@ -1746,33 +2015,49 @@ static void PostInc (ExprDesc* Expr)
/* Get the data type */
Flags = TypeOf (Expr->Type);
/* We are allowed by the C standard to defer the inc operation until
** the this expression is used, so that we don't need to save and reload
** the original value.
*/
/* Emit smaller code if a char variable is at a constant location */
if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst(Expr)) {
if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst (Expr)) {
LoadExpr (CF_NONE, Expr);
AddCodeLine ("inc %s", ED_GetLabelName(Expr, 0));
AddCodeLine ("inc %s", ED_GetLabelName (Expr, 0));
} else {
/* Push the address if needed */
PushAddr (Expr);
Loc = ED_GetLoc (Expr);
if (Loc == E_LOC_PRIMARY || Loc == E_LOC_EXPR) {
/* Push the address if needed */
PushAddr (Expr);
/* Fetch the value and save it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
g_save (Flags | CF_FORCECHAR);
/* Fetch the value and save it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
g_save (Flags | CF_FORCECHAR);
/* If we have a pointer expression, increment by the size of the type */
if (IsTypePtr (Expr->Type)) {
g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
}
/* Store the result back */
Store (Expr, 0);
/* Restore the original value in the primary register */
g_restore (Flags | CF_FORCECHAR);
/* If we have a pointer expression, increment by the size of the type */
if (IsTypePtr (Expr->Type)) {
g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
/* Fetch the value and use it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
/* Defer the increment until the value of this expression is used */;
DeferInc (Expr);
}
/* Store the result back */
Store (Expr, 0);
/* Restore the original value in the primary register */
g_restore (Flags | CF_FORCECHAR);
}
/* The result is always an expression, no reference */
@ -1784,7 +2069,7 @@ static void PostInc (ExprDesc* Expr)
static void PostDec (ExprDesc* Expr)
/* Handle the postdecrement operator */
{
unsigned Flags;
unsigned Flags, Loc;
NextToken ();
@ -1803,32 +2088,43 @@ static void PostDec (ExprDesc* Expr)
Flags = TypeOf (Expr->Type);
/* Emit smaller code if a char variable is at a constant location */
if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst(Expr)) {
if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst (Expr)) {
LoadExpr (CF_NONE, Expr);
AddCodeLine ("dec %s", ED_GetLabelName(Expr, 0));
AddCodeLine ("dec %s", ED_GetLabelName (Expr, 0));
} else {
/* Push the address if needed */
PushAddr (Expr);
Loc = ED_GetLoc (Expr);
if (Loc == E_LOC_PRIMARY || Loc == E_LOC_EXPR) {
/* Push the address if needed */
PushAddr (Expr);
/* Fetch the value and save it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
g_save (Flags | CF_FORCECHAR);
/* Fetch the value and save it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
g_save (Flags | CF_FORCECHAR);
/* If we have a pointer expression, increment by the size of the type */
if (IsTypePtr (Expr->Type)) {
g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
}
/* Store the result back */
Store (Expr, 0);
/* Restore the original value in the primary register */
g_restore (Flags | CF_FORCECHAR);
/* If we have a pointer expression, increment by the size of the type */
if (IsTypePtr (Expr->Type)) {
g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
/* Fetch the value and save it (since it's the result of the expression) */
LoadExpr (CF_NONE, Expr);
/* Defer the decrement until the value of this expression is used */;
DeferDec (Expr);
}
/* Store the result back */
Store (Expr, 0);
/* Restore the original value in the primary register */
g_restore (Flags | CF_FORCECHAR);
}
/* The result is always an expression, no reference */
@ -3263,6 +3559,9 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
/* Load the value */
LoadExpr (CF_FORCECHAR, Expr);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, Expr);
/* Clear the test flag */
ED_RequireNoTest (Expr);
@ -3275,9 +3574,17 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
/* Generate the jump */
g_falsejump (CF_NONE, FalseLab);
} else if (Expr->IVal == 0 && !ED_IsAddrExpr (Expr)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
} else {
/* Constant boolean subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence
** point.
*/
DoDeferred (SQP_KEEP_NONE, Expr);
if (Expr->IVal == 0 && !ED_IsAddrExpr (Expr)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
}
}
}
@ -3306,6 +3613,9 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
ED_RequireTest (&Expr2);
LoadExpr (CF_FORCECHAR, &Expr2);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, &Expr2);
/* Do short circuit evaluation */
if (CurTok.Tok == TOK_BOOL_AND) {
if (HasFalseJump == 0) {
@ -3319,11 +3629,19 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
/* We need the true label for the last expression */
HasTrueJump = 1;
}
} else if (Expr2.IVal == 0 && !ED_IsAddrExpr (&Expr2)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
/* The value of the expression will be false */
ED_MakeConstBool (Expr, 0);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr2);
if (Expr2.IVal == 0 && !ED_IsAddrExpr (&Expr2)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
/* The value of the expression will be false */
ED_MakeConstBool (Expr, 0);
}
}
}
}
@ -3408,6 +3726,9 @@ static void hieOr (ExprDesc *Expr)
/* Get first expr */
LoadExpr (CF_FORCECHAR, Expr);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, Expr);
/* Clear the test flag */
ED_RequireNoTest (Expr);
@ -3421,9 +3742,17 @@ static void hieOr (ExprDesc *Expr)
/* Jump to TrueLab if true */
g_truejump (CF_NONE, TrueLab);
}
} else if (Expr->IVal != 0 || ED_IsAddrExpr (Expr)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
} else {
/* Constant boolean subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence
** point.
*/
DoDeferred (SQP_KEEP_NONE, Expr);
if (Expr->IVal != 0 || ED_IsAddrExpr (Expr)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
}
}
}
@ -3456,17 +3785,28 @@ static void hieOr (ExprDesc *Expr)
ED_RequireTest (&Expr2);
LoadExpr (CF_FORCECHAR, &Expr2);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, &Expr2);
if (HasTrueJump == 0) {
TrueLab = GetLocalLabel();
HasTrueJump = 1;
}
g_truejump (CF_NONE, TrueLab);
}
} else if (Expr2.IVal != 0 || ED_IsAddrExpr (&Expr2)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
/* The result is always true */
ED_MakeConstBool (Expr, 1);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr2);
if (Expr2.IVal != 0 || ED_IsAddrExpr (&Expr2)) {
/* Skip remaining */
Flags |= E_EVAL_UNEVAL;
/* The result is always true */
ED_MakeConstBool (Expr, 1);
}
}
}
@ -3547,11 +3887,22 @@ static void hieQuest (ExprDesc* Expr)
/* Condition codes not set, request a test */
ED_RequireTest (Expr);
LoadExpr (CF_NONE, Expr);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, Expr);
FalseLab = GetLocalLabel ();
g_falsejump (CF_NONE, FalseLab);
} else if (Expr->IVal == 0) {
/* Remember the current code position */
GetCodePos (&SkippedBranch);
} else {
/* Constant boolean subexpression could still have deferred inc/dec
** operations, so just flush their side-effects at this sequence point.
*/
DoDeferred (SQP_KEEP_NONE, Expr);
if (Expr->IVal == 0) {
/* Remember the current code position */
GetCodePos (&SkippedBranch);
}
}
/* Parse second expression. Remember for later if it is a NULL pointer
@ -3563,7 +3914,17 @@ static void hieQuest (ExprDesc* Expr)
if (!ConstantCond || !ED_IsConst (&Expr2)) {
/* Load it into the primary */
LoadExpr (CF_NONE, &Expr2);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_EXPR, &Expr2);
ED_FinalizeRValLoad (&Expr2);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr2);
}
Expr2.Type = PtrConversion (Expr2.Type);
}
@ -3601,7 +3962,17 @@ static void hieQuest (ExprDesc* Expr)
if (!ConstantCond || !ED_IsConst (&Expr3)) {
/* Load it into the primary */
LoadExpr (CF_NONE, &Expr3);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_EXPR, &Expr3);
ED_FinalizeRValLoad (&Expr3);
} else {
/* Constant boolean subexpression could still have deferred inc/
** dec operations, so just flush their side-effects at this
** sequence point.
*/
DoDeferred (SQP_KEEP_NONE, &Expr3);
}
Expr3.Type = PtrConversion (Expr3.Type);
}
@ -4011,6 +4382,9 @@ void hie0 (ExprDesc *Expr)
hie1 (Expr);
while (CurTok.Tok == TOK_COMMA) {
/* 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.
*/
@ -4037,7 +4411,9 @@ void hie0 (ExprDesc *Expr)
void Expression0 (ExprDesc* Expr)
/* Evaluate an expression via hie0 and put the result into the primary register */
/* Evaluate an expression via hie0 and put the result into the primary register.
** The expression is completely evaluated and all side effects complete.
*/
{
unsigned Flags = Expr->Flags & E_MASK_KEEP_RESULT;
@ -4051,6 +4427,9 @@ void Expression0 (ExprDesc* Expr)
if (ED_YetToLoad (Expr)) {
LoadExpr (CF_NONE, Expr);
}
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_EXPR, Expr);
}

View File

@ -17,6 +17,19 @@
/*****************************************************************************/
/* data */
/*****************************************************************************/
#define SQP_KEEP_NONE 0x00
#define SQP_KEEP_TEST 0x01U
#define SQP_KEEP_EAX 0x02U
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
/*****************************************************************************/
/* code */
/*****************************************************************************/
@ -38,6 +51,23 @@ void PushAddr (const ExprDesc* Expr);
** must be saved if it's not constant, before evaluating the rhs.
*/
void InitDeferredOps (void);
/* Init the collection for storing deferred ops */
void DoneDeferredOps (void);
/* Deinit the collection for storing deferred ops */
int GetDeferredOpCount (void);
/* Return how many deferred operations are still waiting in the queque */
void CheckDeferredOpAllDone (void);
/* Check if all deferred operations are done at sequence points.
** Die off if check fails.
*/
void DoDeferred (unsigned Flags, ExprDesc* Expr);
/* Do deferred operations such as post-inc/dec at sequence points */
void Store (ExprDesc* Expr, const Type* StoreType);
/* Store the primary register into the location denoted by lval. If StoreType
** is given, use this type when storing instead of lval->Type. If StoreType
@ -52,7 +82,9 @@ int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
*/
void Expression0 (ExprDesc* Expr);
/* Evaluate an expression via hie0 and put the result into the primary register */
/* Evaluate an expression via hie0 and put the result into the primary register.
** The expression is completely evaluated and all side effects complete.
*/
void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not

View File

@ -105,6 +105,9 @@ void GotoStatement (void)
val = (unsigned char)CurTok.IVal;
NextToken ();
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_NONE, &desc);
if (CPUIsets[CPU] & CPU_ISET_65SC02) {
AddCodeLine ("ldx #$%02X", val * 2);
AddCodeLine ("jmp (.loword(%s),x)", arr->AsmName);
@ -118,6 +121,10 @@ void GotoStatement (void)
(idx = FindSym (CurTok.Ident))) {
hie10 (&desc);
LoadExpr (CF_NONE, &desc);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_EAX, &desc);
AddCodeLine ("asl a");
if (CPUIsets[CPU] & CPU_ISET_65SC02) {

View File

@ -165,6 +165,8 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg)
/* Store the value into the variable */
g_putstatic (CF_REGVAR | TypeOf (Sym->Type), Reg, 0);
/* This has to be done at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);
}
/* Mark the variable as referenced */
@ -273,6 +275,8 @@ static void ParseAutoDecl (Declaration* Decl)
/* Push the value */
g_push (Flags | TypeOf (Sym->Type), Expr.IVal);
/* This has to be done at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);
}
/* Mark the variable as referenced */
@ -349,6 +353,9 @@ static void ParseAutoDecl (Declaration* Decl)
/* Store the value into the variable */
g_putstatic (CF_STATIC | TypeOf (Sym->Type), DataLabel, 0);
/* This has to be done at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);
}
/* Mark the variable as referenced */
@ -525,6 +532,9 @@ static void ParseOneDecl (const DeclSpec* Spec)
}
}
/* Make sure we aren't missing some work */
CheckDeferredOpAllDone ();
}

View File

@ -245,6 +245,9 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
LoadExpr (CF_NONE, &Arg3.Expr);
}
/* We still need to append deferred inc/dec before calling into the function */
DoDeferred (SQP_KEEP_EAX, &Arg3.Expr);
/* Emit the actual function call. This will also cleanup the stack. */
g_call (CF_FIXARGC, Func_memcpy, ParamSize);
@ -594,6 +597,9 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
LoadExpr (CF_NONE, &Arg3.Expr);
}
/* We still need to append deferred inc/dec before calling into the function */
DoDeferred (SQP_KEEP_EAX, &Arg3.Expr);
/* Emit the actual function call. This will also cleanup the stack. */
g_call (CF_FIXARGC, MemSet? Func_memset : Func__bzero, ParamSize);
@ -808,6 +814,9 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
LoadExpr (CF_NONE, &Arg2.Expr);
}
/* We still need to append deferred inc/dec before calling into the function */
DoDeferred (SQP_KEEP_EAX, &Arg2.Expr);
/* Emit the actual function call. This will also cleanup the stack. */
g_call (CF_FIXARGC, Func_strcmp, ParamSize);
@ -1007,6 +1016,9 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
LoadExpr (CF_NONE, &Arg2.Expr);
}
/* We still need to append deferred inc/dec before calling into the function */
DoDeferred (SQP_KEEP_EAX, &Arg2.Expr);
/* Emit the actual function call. This will also cleanup the stack. */
g_call (CF_FIXARGC, Func_strcpy, ParamSize);
@ -1193,6 +1205,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Evaluate the parameter */
hie1 (&Arg);
/* We still need to append deferred inc/dec before calling into the function */
DoDeferred (SQP_KEEP_EAX, &Arg);
/* Check if the argument is an array. If so, remember the element count.
** Otherwise set the element count to undefined.
*/

View File

@ -352,6 +352,9 @@ static void ReturnStatement (void)
LoadExpr (CF_NONE, &Expr);
}
}
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_EAX, &Expr);
}
} else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) {

View File

@ -66,6 +66,9 @@ unsigned Test (unsigned Label, int Invert)
/* Check for a constant expression */
if (ED_IsConstAbs (&Expr)) {
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);
/* Result is constant, so we know the outcome */
Result = (Expr.IVal != 0);
@ -79,6 +82,9 @@ unsigned Test (unsigned Label, int Invert)
} else if (ED_IsAddrExpr (&Expr)) {
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);
/* Object addresses are non-NULL */
Result = 1;
@ -93,6 +99,9 @@ unsigned Test (unsigned Label, int Invert)
/* Load the value into the primary register */
LoadExpr (CF_FORCECHAR, &Expr);
/* Append deferred inc/dec at sequence point */
DoDeferred (SQP_KEEP_TEST, &Expr);
/* Generate the jump */
if (Invert) {
g_truejump (CF_NONE, Label);