From b5cc68d6e2afe6d249ad31c83bf64382eade7b49 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:41:25 +0200 Subject: [PATCH] Do not save any register variables when entering main(). Do not restore the C stack when leaving main(). Both are unnecessary and just bloat the executable. --- src/cc65/codegen.c | 45 +++++++++++++++++++++++++-------------------- src/cc65/codegen.h | 2 +- src/cc65/function.c | 8 +++++--- src/cc65/locals.c | 44 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 69dcc1c6c..45823fab6 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -507,34 +507,39 @@ void g_enter (unsigned flags, unsigned argsize) -void g_leave (void) +void g_leave (int IsMainFunc) /* Function epilogue */ { - /* How many bytes of locals do we have to drop? */ - unsigned ToDrop = (unsigned) -StackPtr; + /* In the main function nothing has to be dropped because the program + ** is terminated anyway. + */ + if (!IsMainFunc) { + /* How many bytes of locals do we have to drop? */ + unsigned ToDrop = (unsigned) -StackPtr; - /* If we didn't have a variable argument list, don't call leave */ - if (funcargs >= 0) { + /* If we didn't have a variable argument list, don't call leave */ + if (funcargs >= 0) { - /* Drop stackframe if needed */ - g_drop (ToDrop + funcargs); + /* Drop stackframe if needed */ + g_drop (ToDrop + funcargs); - } else if (StackPtr != 0) { + } else if (StackPtr != 0) { + + /* We've a stack frame to drop */ + if (ToDrop > 255) { + g_drop (ToDrop); /* Inlines the code */ + AddCodeLine ("jsr leave"); + } else { + AddCodeLine ("ldy #$%02X", ToDrop); + AddCodeLine ("jsr leavey"); + } - /* We've a stack frame to drop */ - if (ToDrop > 255) { - g_drop (ToDrop); /* Inlines the code */ - AddCodeLine ("jsr leave"); } else { - AddCodeLine ("ldy #$%02X", ToDrop); - AddCodeLine ("jsr leavey"); + + /* Nothing to drop */ + AddCodeLine ("jsr leave"); + } - - } else { - - /* Nothing to drop */ - AddCodeLine ("jsr leave"); - } /* Add the final rts */ diff --git a/src/cc65/codegen.h b/src/cc65/codegen.h index 8e04b45e4..b95df5cfb 100644 --- a/src/cc65/codegen.h +++ b/src/cc65/codegen.h @@ -247,7 +247,7 @@ void g_scale (unsigned flags, long val); void g_enter (unsigned flags, unsigned argsize); /* Function prologue */ -void g_leave (void); +void g_leave (int IsMainFunc); /* Function epilogue */ diff --git a/src/cc65/function.c b/src/cc65/function.c index a4b860251..d5cab3993 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -646,11 +646,13 @@ void NewFunc (SymEntry* Func, FuncDesc* D) /* Output the function exit code label */ g_defcodelabel (F_GetRetLab (CurrentFunc)); - /* Restore the register variables */ - F_RestoreRegVars (CurrentFunc); + /* Restore the register variables (not necessary for main function) */ + if (!F_IsMainFunc (CurrentFunc)) { + F_RestoreRegVars (CurrentFunc); + } /* Generate the exit code */ - g_leave (); + g_leave (F_IsMainFunc (CurrentFunc)); /* Emit references to imports/exports */ EmitExternals (); diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 34d762324..c4d0aa25b 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -111,22 +111,31 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg) /* Get the size of the variable */ unsigned Size = SizeOf (Decl->Type); - /* Save the current contents of the register variable on stack */ - F_AllocLocalSpace (CurrentFunc); - g_save_regvars (Reg, Size); - - /* Add the symbol to the symbol table. We do that now, because for register - ** variables the current stack pointer is implicitly used as location for - ** the save area. - */ - Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); - /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { /* Skip the '=' */ NextToken (); + /* If the register variable is initialized, the initialization code may + ** access other already declared variables. This means that we have to + ** allocate them now. + */ + F_AllocLocalSpace (CurrentFunc); + + /* Save the current contents of the register variable on stack. This is + ** not necessary for the main function. + */ + if (!F_IsMainFunc (CurrentFunc)) { + g_save_regvars (Reg, Size); + } + + /* Add the symbol to the symbol table. We do that now, because for + ** register variables the current stack pointer is implicitly used + ** as location for the save area (unused in case of main()). + */ + Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); + /* Special handling for compound types */ if (IsCompound) { @@ -173,6 +182,21 @@ static void ParseRegisterDecl (Declarator* Decl, int Reg) /* Mark the variable as referenced */ Sym->Flags |= SC_REF; + } else { + + /* Save the current contents of the register variable on stack. This is + ** not necessary for the main function. + */ + if (!F_IsMainFunc (CurrentFunc)) { + F_AllocLocalSpace (CurrentFunc); + g_save_regvars (Reg, Size); + } + + /* Add the symbol to the symbol table. We do that now, because for + ** register variables the current stack pointer is implicitly used + ** as location for the save area (unused in case of main()). + */ + Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); } /* Cannot allocate a variable of unknown size */