From d8279302a947f26f248929eac552c7ed0c465cee Mon Sep 17 00:00:00 2001
From: cuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Date: Tue, 15 Jun 2004 20:29:49 +0000
Subject: [PATCH] Make the -O and --codesize options stackable. Copy the
 current optimization settings into a code segment on creation.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3129 b7a2c559-68d2-44c3-8de9-860c34a00d81
---
 src/cc65/codegen.c | 32 ++++++++++++++++----------------
 src/cc65/codeopt.c |  6 +++---
 src/cc65/codeseg.c |  7 ++++++-
 src/cc65/codeseg.h |  8 ++++++--
 src/cc65/compile.c |  7 ++++---
 src/cc65/expr.c    |  2 +-
 src/cc65/global.c  |  5 ++---
 src/cc65/global.h  |  7 +++----
 src/cc65/main.c    | 14 ++++++++------
 src/cc65/stdfunc.c |  4 ++--
 10 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c
index 88cebe9a4..14297e928 100644
--- a/src/cc65/codegen.c
+++ b/src/cc65/codegen.c
@@ -511,7 +511,7 @@ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes)
     /* Generate code */
     if (Bytes == 1) {
 
-        if (CodeSizeFactor < 165) {
+        if (IS_Get (&CodeSizeFactor) < 165) {
             ldyconst (StackOffs);
             ldxconst (RegOffs);
             AddCodeLine ("jsr regswap1");
@@ -601,7 +601,7 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes)
        	AddCodeLine ("lda (sp),y");
        	AddCodeLine ("sta regbank%+d", RegOffs+1);
 
-    } else if (Bytes == 3 && CodeSizeFactor >= 133) {
+    } else if (Bytes == 3 && IS_Get (&CodeSizeFactor) >= 133) {
 
        	ldyconst (StackOffs);
        	AddCodeLine ("lda (sp),y");
@@ -915,7 +915,7 @@ void g_leasp (int offs)
        	AddCodeLine ("lda sp");
        	AddCodeLine ("ldx sp+1");
     } else {
-       	if (CodeSizeFactor < 300) {
+       	if (IS_Get (&CodeSizeFactor) < 300) {
        	    ldaconst (offs);         		/* Load A with offset value */
        	    AddCodeLine ("jsr leaasp");	/* Load effective address */
        	} else {
@@ -963,7 +963,7 @@ void g_leavariadic (int Offs)
     AddCodeLine ("lda (sp),y");
 
     /* Add the value of the stackpointer */
-    if (CodeSizeFactor > 250) {
+    if (IS_Get (&CodeSizeFactor) > 250) {
 	unsigned L = GetLocalLabel();
        	AddCodeLine ("ldx sp+1");
        	AddCodeLine ("clc");
@@ -1060,7 +1060,7 @@ void g_putlocal (unsigned Flags, int Offs, long Val)
 		}
 		AddCodeLine ("sta (sp),y");
 	    } else {
-		if ((Flags & CF_NOKEEP) == 0 || CodeSizeFactor < 160) {
+		if ((Flags & CF_NOKEEP) == 0 || IS_Get (&CodeSizeFactor) < 160) {
 		    ldyconst (Offs);
 		    AddCodeLine ("jsr staxysp");
 		} else {
@@ -1258,7 +1258,7 @@ void g_reglong (unsigned Flags)
             if (Flags & CF_FORCECHAR) {
                 /* Conversion is from char */
                 if (Flags & CF_UNSIGNED) {
-                    if (CodeSizeFactor >= 200) {
+                    if (IS_Get (&CodeSizeFactor) >= 200) {
                         AddCodeLine ("ldx #$00");
                         AddCodeLine ("stx sreg");
                         AddCodeLine ("stx sreg+1");
@@ -1266,7 +1266,7 @@ void g_reglong (unsigned Flags)
                         AddCodeLine ("jsr aulong");
                     }
                 } else {
-                    if (CodeSizeFactor >= 366) {
+                    if (IS_Get (&CodeSizeFactor) >= 366) {
                         L = GetLocalLabel();
                         AddCodeLine ("ldx #$00");
                         AddCodeLine ("cmp #$80");
@@ -1284,7 +1284,7 @@ void g_reglong (unsigned Flags)
 
 	case CF_INT:
 	    if (Flags & CF_UNSIGNED) {
-	    	if (CodeSizeFactor >= 200) {
+	    	if (IS_Get (&CodeSizeFactor) >= 200) {
 	    	    ldyconst (0);
 	    	    AddCodeLine ("sty sreg");
 	  	    AddCodeLine ("sty sreg+1");
@@ -1425,7 +1425,7 @@ void g_scale (unsigned flags, long val)
      	     	    /* FALLTHROUGH */
 
      	     	case CF_INT:
-     		    if (CodeSizeFactor >= (p2+1)*130U) {
+     		    if (IS_Get (&CodeSizeFactor) >= (p2+1)*130) {
      	     		AddCodeLine ("stx tmp1");
      	     	  	while (p2--) {
      	     		    AddCodeLine ("asl a");
@@ -1487,7 +1487,7 @@ void g_scale (unsigned flags, long val)
 
      		case CF_INT:
      		    if (flags & CF_UNSIGNED) {
-			if (CodeSizeFactor >= (p2+1)*130U) {
+			if (IS_Get (&CodeSizeFactor) >= (p2+1)*130) {
 			    AddCodeLine ("stx tmp1");
 			    while (p2--) {
 	     		    	AddCodeLine ("lsr tmp1");
@@ -1498,7 +1498,7 @@ void g_scale (unsigned flags, long val)
      			    AddCodeLine ("jsr lsrax%d", p2);
 			}
      		    } else {
-			if (CodeSizeFactor >= (p2+1)*150U) {
+			if (IS_Get (&CodeSizeFactor) >= (p2+1)*150) {
 			    AddCodeLine ("stx tmp1");
 			    while (p2--) {
 			    	AddCodeLine ("cpx #$80");
@@ -1788,7 +1788,7 @@ void g_addeqlocal (unsigned flags, int offs, unsigned long val)
        	case CF_INT:
 	    ldyconst (offs);
      	    if (flags & CF_CONST) {
-		if (CodeSizeFactor >= 400) {
+		if (IS_Get (&CodeSizeFactor) >= 400) {
 		    AddCodeLine ("clc");
 		    AddCodeLine ("lda #$%02X", (int)(val & 0xFF));
 		    AddCodeLine ("adc (sp),y");
@@ -1848,7 +1848,7 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val)
      	    break;
 
        	case CF_INT:
-	    if (CodeSizeFactor >= 200) {
+	    if (IS_Get (&CodeSizeFactor) >= 200) {
 		/* Lots of code, use only if size is not important */
        	       	AddCodeLine ("sta ptr1");
 		AddCodeLine ("stx ptr1+1");
@@ -2062,7 +2062,7 @@ void g_subeqind (unsigned flags, unsigned offs, unsigned long val)
      	    break;
 
        	case CF_INT:
-	    if (CodeSizeFactor >= 200) {
+	    if (IS_Get (&CodeSizeFactor) >= 200) {
 		/* Lots of code, use only if size is not important */
 		AddCodeLine ("sta ptr1");
        	       	AddCodeLine ("stx ptr1+1");
@@ -3272,7 +3272,7 @@ void g_inc (unsigned flags, unsigned long val)
 		AddCodeLine ("bne %s", LocalLabelName (L));
 		AddCodeLine ("inx");
 		g_defcodelabel (L);
-     	    } else if (CodeSizeFactor < 200) {
+     	    } else if (IS_Get (&CodeSizeFactor) < 200) {
      		/* Use jsr calls */
      		if (val <= 8) {
      		    AddCodeLine ("jsr incax%lu", val);
@@ -3360,7 +3360,7 @@ void g_dec (unsigned flags, unsigned long val)
 	    /* FALLTHROUGH */
 
      	case CF_INT:
-	    if (CodeSizeFactor < 200) {
+	    if (IS_Get (&CodeSizeFactor) < 200) {
 		/* Use subroutines */
 		if (val <= 8) {
 		    AddCodeLine ("jsr decax%d", (int) val);
diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c
index 7d1109a6f..fefd001f2 100644
--- a/src/cc65/codeopt.c
+++ b/src/cc65/codeopt.c
@@ -1908,7 +1908,7 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max)
     /* Don't run the function if it is disabled or if it is prohibited by the
      * code size factor
      */
-    if (F->Disabled || F->CodeSizeFactor > CodeSizeFactor) {
+    if (F->Disabled || F->CodeSizeFactor > S->CodeSizeFactor) {
     	return 0;
     }
 
@@ -2093,7 +2093,7 @@ static unsigned RunOptGroup6 (CodeSeg* S)
     unsigned Changes = 0;
     unsigned C;
 
-    if (CodeSizeFactor <= 100) {
+    if (S->CodeSizeFactor <= 100) {
         /* Optimize for size, that is replace operations by shorter ones, even
          * if this does hinder further optimizations (no problem since we're
          * done soon).
@@ -2142,7 +2142,7 @@ void RunOpt (CodeSeg* S)
     const char* StatFileName;
 
     /* If we shouldn't run the optimizer, bail out */
-    if (!Optimize) {
+    if (!S->Optimize) {
       	return;
     }
 
diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c
index 1126e08ee..c27f44b3d 100644
--- a/src/cc65/codeseg.c
+++ b/src/cc65/codeseg.c
@@ -50,11 +50,12 @@
 #include "asmlabel.h"
 #include "codeent.h"
 #include "codeinfo.h"
+#include "codeseg.h"
 #include "datatype.h"
 #include "error.h"
+#include "global.h"
 #include "ident.h"
 #include "symentry.h"
-#include "codeseg.h"
 
 
 
@@ -471,6 +472,10 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
 	S->ExitRegs = REG_NONE;
     }
 
+    /* Copy the global optimization settings */
+    S->Optimize       = (unsigned char) IS_Get (&Optimize);
+    S->CodeSizeFactor = (unsigned) IS_Get (&CodeSizeFactor);
+
     /* Return the new struct */
     return S;
 }
diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h
index cde8c4ff1..100bb2604 100644
--- a/src/cc65/codeseg.h
+++ b/src/cc65/codeseg.h
@@ -79,8 +79,12 @@ struct CodeSeg {
     SymEntry*	    Func;	  		/* Owner function */
     Collection	    Entries;	  		/* List of code entries */
     Collection	    Labels;	  		/* Labels for next insn */
-    CodeLabel* 	    LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
+    CodeLabel* 	    LabelHash[CS_LABEL_HASH_SIZE]; /* Label hash table */
     unsigned short  ExitRegs;			/* Register use on exit */
+
+    /* Optimization settings for this segment */
+    unsigned char   Optimize;                   /* On/off switch */
+    unsigned        CodeSizeFactor;
 };
 
 
@@ -287,7 +291,7 @@ void CS_GenRegInfo (CodeSeg* S);
 
 
 /* End of codeseg.h */
-#endif
+#endif                                          
 
 
 
diff --git a/src/cc65/compile.c b/src/cc65/compile.c
index 7edd3ae17..1870b9a1c 100644
--- a/src/cc65/compile.c
+++ b/src/cc65/compile.c
@@ -295,10 +295,11 @@ void Compile (const char* FileName)
      * IS_Get functions access the values in effect now, regardless of any
      * changes using #pragma later.
      */
-    if (Optimize) {
+    if (IS_Get (&Optimize)) {  
+        long CodeSize = IS_Get (&CodeSizeFactor);
 	DefineNumericMacro ("__OPT__", 1);
-	if (FavourSize == 0) {
-	    DefineNumericMacro ("__OPT_i__", 1);
+       	if (CodeSize > 100) {
+	    DefineNumericMacro ("__OPT_i__", CodeSize);
 	}
 	if (IS_Get (&EnableRegVars)) {
 	    DefineNumericMacro ("__OPT_r__", 1);
diff --git a/src/cc65/expr.c b/src/cc65/expr.c
index e7c695799..6cff40326 100644
--- a/src/cc65/expr.c
+++ b/src/cc65/expr.c
@@ -367,7 +367,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
      * (instead of pushing) is enabled.
      *
      */
-    if (CodeSizeFactor >= 200) {
+    if (IS_Get (&CodeSizeFactor) >= 200) {
 
 	/* Calculate the number and size of the parameters */
 	FrameParams = Func->ParamCount;
diff --git a/src/cc65/global.c b/src/cc65/global.c
index 2e862a894..610b80c8b 100644
--- a/src/cc65/global.c
+++ b/src/cc65/global.c
@@ -48,10 +48,7 @@ unsigned char DebugInfo		= 0;	/* Add debug info to the obj */
 unsigned char CreateDep		= 0;	/* Create a dependency file */
 unsigned char ANSI   	       	= 0;	/* Strict ANSI flag */
 unsigned char NoWarn		= 0;   	/* Suppress warnings */
-unsigned char Optimize		= 0;   	/* Optimize flag */
 unsigned long OptDisable	= 0;	/* Optimizer passes to disable */
-unsigned char FavourSize	= 1;   	/* Favour size over speed */
-unsigned      CodeSizeFactor	= 100;	/* Size factor for generated code */
 unsigned      RegisterSpace     = 6;    /* Space available for register vars */
 
 /* Stackable options */
@@ -63,6 +60,8 @@ IntStack RegVarsToCallStack = INTSTACK(0);  /* Save reg variables on call stack
 IntStack StaticLocals       = INTSTACK(0);  /* Make local variables static */
 IntStack SignedChars        = INTSTACK(0);  /* Make characters signed by default */
 IntStack CheckStack         = INTSTACK(0);  /* Generate stack overflow checks */
+IntStack Optimize      	    = INTSTACK(0);  /* Optimize flag */
+IntStack CodeSizeFactor	    = INTSTACK(100);/* Size factor for generated code */
 
 
 
diff --git a/src/cc65/global.h b/src/cc65/global.h
index 93032dae8..11ff82b3c 100644
--- a/src/cc65/global.h
+++ b/src/cc65/global.h
@@ -48,16 +48,13 @@
 /*****************************************************************************/
 
 
-
+                        
 extern unsigned char	AddSource;		/* Add source lines as comments */
 extern unsigned char	DebugInfo;		/* Add debug info to the obj */
 extern unsigned char	CreateDep;		/* Create a dependency file */
 extern unsigned char	ANSI;			/* Strict ANSI flag */
 extern unsigned char	NoWarn;			/* Suppress warnings */
-extern unsigned char	Optimize;		/* Optimize flag */
 extern unsigned long	OptDisable;		/* Optimizer passes to disable */
-extern unsigned char	FavourSize;		/* Favour size over speed */
-extern unsigned	       	CodeSizeFactor;		/* Size factor for generated code */
 extern unsigned         RegisterSpace;          /* Space available for register vars */
 
 /* Stackable options */
@@ -69,6 +66,8 @@ extern IntStack         RegVarsToCallStack;	/* Save reg variables on call stack
 extern IntStack         StaticLocals;		/* Make local variables static */
 extern IntStack         SignedChars;		/* Make characters signed by default */
 extern IntStack         CheckStack;		/* Generate stack overflow checks */
+extern IntStack         Optimize;		/* Optimize flag */
+extern IntStack         CodeSizeFactor;		/* Size factor for generated code */
 
 
 
diff --git a/src/cc65/main.c b/src/cc65/main.c
index bb8864698..c272902dd 100644
--- a/src/cc65/main.c
+++ b/src/cc65/main.c
@@ -374,12 +374,15 @@ static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg)
 static void OptCodeSize (const char* Opt, const char* Arg)
 /* Handle the --codesize option */
 {
+    unsigned Factor;
+    char     BoundsCheck;
+
     /* Numeric argument expected */
-    if (sscanf (Arg, "%u", &CodeSizeFactor) != 1 ||
-	CodeSizeFactor < 100 ||
-       	CodeSizeFactor > 1000) {
+    if (sscanf (Arg, "%u%c", &Factor, &BoundsCheck) != 1 ||
+        Factor < 10 || Factor > 1000) {
 	AbEnd ("Argument for %s is invalid", Opt);
     }
+    IS_Set (&CodeSizeFactor, Factor);
 }
 
 
@@ -801,7 +804,7 @@ int main (int argc, char* argv[])
 		    break;
 
 		case 'O':
-		    Optimize = 1;
+		    IS_Set (&Optimize, 1);
 	    	    P = Arg + 2;
 		    while (*P) {
 		    	switch (*P++) {
@@ -809,8 +812,7 @@ int main (int argc, char* argv[])
      		    	     	sscanf (P, "%lx", (long*) &OptDisable);
 		    	     	break;
 	       	    	    case 'i':
-	       	    	     	FavourSize = 0;
-			        CodeSizeFactor = 200;
+			        IS_Set (&CodeSizeFactor, 200);
     	       	    	     	break;
 	       	    	    case 'r':
 	       	    	  	IS_Set (&EnableRegVars, 1);
diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c
index 410d36e5c..74b9b8c2a 100644
--- a/src/cc65/stdfunc.c
+++ b/src/cc65/stdfunc.c
@@ -638,7 +638,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 
     } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
                ED_IsConstAbsInt (&Arg2.Expr) &&
-               (Arg2.Expr.IVal != 0 || CodeSizeFactor > 200)) {
+               (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
 
         /* Remove all of the generated code but the load of the first
          * argument.
@@ -1015,7 +1015,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
      * requested on the command line, and the code size factor is more than
      * 400 (code is 13 bytes vs. 3 for a jsr call).
      */
-    } else if (CodeSizeFactor > 400 && IS_Get (&InlineStdFuncs)) {
+    } else if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&InlineStdFuncs)) {
 
         /* Load the expression into the primary */
         LoadExpr (CF_NONE, &Arg);