]> git.sur5r.net Git - cc65/commitdiff
Re-added register variables.
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 25 Nov 2002 15:05:15 +0000 (15:05 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 25 Nov 2002 15:05:15 +0000 (15:05 +0000)
Changed/added several optimizer steps to detect register variables correctly
or to handle them in a special way.

git-svn-id: svn://svn.cc65.org/cc65/trunk@1636 b7a2c559-68d2-44c3-8de9-860c34a00d81

18 files changed:
src/cc65/codeent.c
src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/codeinfo.c
src/cc65/codeseg.c
src/cc65/coptadd.c
src/cc65/coptadd.h
src/cc65/coptstop.c
src/cc65/declare.c
src/cc65/function.c
src/cc65/function.h
src/cc65/locals.c
src/cc65/reginfo.c
src/cc65/reginfo.h
src/cc65/symentry.c
src/cc65/symentry.h
src/cc65/symtab.c
src/cc65/symtab.h

index 6e96aaa071b0dc2eafa2bf1136a369022e0a142b..259cea5a5d5b1e9fe1ad9bad387da080e2a048f3 100644 (file)
@@ -461,11 +461,11 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            /* We don't know the value of the carry, so the result is
             * always unknown.
             */
-           Out->RegA = -1;
+           Out->RegA = UNKNOWN_REGVAL;
            break;
 
        case OP65_AND:
-                   if (In->RegA >= 0) {
+                   if (RegValIsKnown (In->RegA)) {
                if (CE_KnownImm (E)) {
                    Out->RegA = In->RegA & (short) E->Num;
                } else if (E->AM == AM65_ZP) {
@@ -480,11 +480,11 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                            Out->RegA = In->RegA & In->SRegHi;
                            break;
                        default:
-                           Out->RegA = -1;
+                           Out->RegA = UNKNOWN_REGVAL;
                            break;
                    }
                } else {
-                   Out->RegA = -1;
+                   Out->RegA = UNKNOWN_REGVAL;
                }
            }
            break;
@@ -565,7 +565,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            break;
 
        case OP65_DEA:
-           if (In->RegA >= 0) {
+                   if (RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA - 1) & 0xFF;
            }
            break;
@@ -592,19 +592,19 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            break;
 
        case OP65_DEX:
-                   if (In->RegX >= 0) {
+                   if (RegValIsKnown (In->RegX)) {
                Out->RegX = (In->RegX - 1) & 0xFF;
            }
            break;
 
        case OP65_DEY:
-                   if (In->RegY >= 0) {
+                   if (RegValIsKnown (In->RegY)) {
                Out->RegY = (In->RegY - 1) & 0xFF;
            }
            break;
 
        case OP65_EOR:
-                   if (In->RegA >= 0) {
+                   if (RegValIsKnown (In->RegA)) {
                if (CE_KnownImm (E)) {
                    Out->RegA = In->RegA ^ (short) E->Num;
                } else if (E->AM == AM65_ZP) {
@@ -619,17 +619,17 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                            Out->RegA = In->RegA ^ In->SRegHi;
                            break;
                        default:
-                           Out->RegA = -1;
+                           Out->RegA = UNKNOWN_REGVAL;
                            break;
                    }
                } else {
-                   Out->RegA = -1;
+                   Out->RegA = UNKNOWN_REGVAL;
                }
            }
            break;
 
        case OP65_INA:
-           if (In->RegA >= 0) {
+           if (RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA + 1) & 0xFF;
            }
            break;
@@ -656,13 +656,13 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            break;
 
        case OP65_INX:
-           if (In->RegX >= 0) {
+           if (RegValIsKnown (In->RegX)) {
                Out->RegX = (In->RegX + 1) & 0xFF;
            }
            break;
 
        case OP65_INY:
-           if (In->RegY >= 0) {
+           if (RegValIsKnown (In->RegY)) {
                Out->RegY = (In->RegY + 1) & 0xFF;
            }
            break;
@@ -692,22 +692,22 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            /* Get the code info for the function */
            GetFuncInfo (E->Arg, &Use, &Chg);
            if (Chg & REG_A) {
-               Out->RegA = -1;
+               Out->RegA = UNKNOWN_REGVAL;
            }
            if (Chg & REG_X) {
-               Out->RegX = -1;
+               Out->RegX = UNKNOWN_REGVAL;
            }
            if (Chg & REG_Y) {
-               Out->RegY = -1;
+               Out->RegY = UNKNOWN_REGVAL;
            }
            if (Chg & REG_TMP1) {
-               Out->Tmp1 = -1;
+               Out->Tmp1 = UNKNOWN_REGVAL;
            }
             if (Chg & REG_SREG_LO) {
-               Out->SRegLo = -1;
+               Out->SRegLo = UNKNOWN_REGVAL;
            }
            if (Chg & REG_SREG_HI) {
-               Out->SRegHi = -1;
+               Out->SRegHi = UNKNOWN_REGVAL;
            }
                    /* ## FIXME: Quick hack for some known functions: */
            if (strcmp (E->Arg, "tosandax") == 0) {
@@ -750,12 +750,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                        Out->RegA = In->SRegHi;
                        break;
                    default:
-                       Out->RegA = -1;
+                       Out->RegA = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* A is now unknown */
-               Out->RegA = -1;
+               Out->RegA = UNKNOWN_REGVAL;
            }
            break;
 
@@ -774,12 +774,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                        Out->RegX = In->SRegHi;
                        break;
                    default:
-                       Out->RegX = -1;
+                       Out->RegX = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* X is now unknown */
-               Out->RegX = -1;
+               Out->RegX = UNKNOWN_REGVAL;
            }
            break;
 
@@ -798,12 +798,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                        Out->RegY = In->SRegHi;
                        break;
                    default:
-                       Out->RegY = -1;
+                       Out->RegY = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* Y is now unknown */
-               Out->RegY = -1;
+               Out->RegY = UNKNOWN_REGVAL;
            }
            break;
 
@@ -832,7 +832,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            break;
 
        case OP65_ORA:
-           if (In->RegA >= 0) {
+           if (RegValIsKnown (In->RegA)) {
                if (CE_KnownImm (E)) {
                    Out->RegA = In->RegA | (short) E->Num;
                } else if (E->AM == AM65_ZP) {
@@ -847,12 +847,12 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                            Out->RegA = In->RegA | In->SRegHi;
                            break;
                        default:
-                           Out->RegA = -1;
+                           Out->RegA = UNKNOWN_REGVAL;
                            break;
                    }
                } else {
                    /* A is now unknown */
-                   Out->RegA = -1;
+                   Out->RegA = UNKNOWN_REGVAL;
                }
            }
            break;
@@ -887,17 +887,17 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
        case OP65_ROL:
            /* We don't know the value of the carry bit */
            if (E->AM == AM65_ACC) {
-               Out->RegA = -1;
+               Out->RegA = UNKNOWN_REGVAL;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Chg, In)) {
                    case REG_TMP1:
-                       Out->Tmp1 = -1;
+                       Out->Tmp1 = UNKNOWN_REGVAL;
                        break;
                    case REG_SREG_LO:
-                       Out->SRegLo = -1;
+                       Out->SRegLo = UNKNOWN_REGVAL;
                        break;
                    case REG_SREG_HI:
-                       Out->SRegHi = -1;
+                       Out->SRegHi = UNKNOWN_REGVAL;
                        break;
                }
            } else if (E->AM == AM65_ZPX) {
@@ -909,17 +909,17 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
        case OP65_ROR:
            /* We don't know the value of the carry bit */
            if (E->AM == AM65_ACC) {
-               Out->RegA = -1;
+               Out->RegA = UNKNOWN_REGVAL;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Chg, In)) {
                    case REG_TMP1:
-                       Out->Tmp1 = -1;
+                       Out->Tmp1 = UNKNOWN_REGVAL;
                        break;
                    case REG_SREG_LO:
-                       Out->SRegLo = -1;
+                       Out->SRegLo = UNKNOWN_REGVAL;
                        break;
                    case REG_SREG_HI:
-                       Out->SRegHi = -1;
+                       Out->SRegHi = UNKNOWN_REGVAL;
                        break;
                }
            } else if (E->AM == AM65_ZPX) {
@@ -1052,13 +1052,13 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                } else {
                    switch (GetKnownReg (E->Chg, In)) {
                        case REG_TMP1:
-                           Out->Tmp1 = -1;
+                           Out->Tmp1 = UNKNOWN_REGVAL;
                            break;
                        case REG_SREG_LO:
-                           Out->SRegLo = -1;
+                           Out->SRegLo = UNKNOWN_REGVAL;
                            break;
                        case REG_SREG_HI:
-                           Out->SRegHi = -1;
+                           Out->SRegHi = UNKNOWN_REGVAL;
                            break;
                    }
                }
@@ -1085,13 +1085,13 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
                } else {
                    switch (GetKnownReg (E->Chg, In)) {
                        case REG_TMP1:
-                           Out->Tmp1 = -1;
+                           Out->Tmp1 = UNKNOWN_REGVAL;
                            break;
                        case REG_SREG_LO:
-                           Out->SRegLo = -1;
+                           Out->SRegLo = UNKNOWN_REGVAL;
                            break;
                        case REG_SREG_HI:
-                           Out->SRegHi = -1;
+                           Out->SRegHi = UNKNOWN_REGVAL;
                            break;
                    }
                }
@@ -1099,7 +1099,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
            break;
 
        case OP65_TSX:
-           Out->RegX = -1;
+           Out->RegX = UNKNOWN_REGVAL;
            break;
 
        case OP65_TXA:
index 6e05351d0d22d1d335214ae46b601f774f0fde6c..a9f5dd6947854c8519492cc2b5f5697bb05e5117 100644 (file)
@@ -132,9 +132,9 @@ static const char* GetLabelName (unsigned Flags, unsigned long Label, long Offs)
            break;
 
        default:
-           Internal ("Invalid address flags");
+           Internal ("Invalid address flags: %04X", Flags);
     }
-                   
+
     /* Return a pointer to the static buffer */
     return Buf;
 }
@@ -485,11 +485,51 @@ void g_leave (void)
 
 
 /*****************************************************************************/
-/*                           Register variables                             */
+/*                                   Register variables                             */
 /*****************************************************************************/
 
 
 
+void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes)
+/* Swap a register variable with a location on the stack */
+{
+    /* Calculate the actual stack offset and check it */
+    StackOffs -= oursp;
+    CheckLocalOffs (StackOffs);
+
+    /* Generate code */
+    if (Bytes == 1) {
+
+        if (CodeSizeFactor < 165) {
+            ldyconst (StackOffs);
+            ldxconst (RegOffs);
+            AddCodeLine ("jsr regswap1");
+        } else {
+            ldyconst (StackOffs);
+            AddCodeLine ("lda (sp),y");
+            AddCodeLine ("ldx regbank%+d", RegOffs);
+            AddCodeLine ("sta regbank%+d", RegOffs);
+            AddCodeLine ("txa");
+            AddCodeLine ("sta (sp),y");
+        }
+
+    } else if (Bytes == 2) {
+
+        ldyconst (StackOffs);
+        ldxconst (RegOffs);
+        AddCodeLine ("jsr regswap2");
+
+    } else {
+
+        ldyconst (StackOffs);
+        ldxconst (RegOffs);
+        ldaconst (Bytes);
+        AddCodeLine ("jsr regswap");
+    }
+}
+
+
+
 void g_save_regvars (int RegOffs, unsigned Bytes)
 /* Save register variables */
 {
index 649d5e789af278121a5a8301b6a4ac3a03028c05..17dfcd513c0537de1fb1dc8c5564cadd30b8327a 100644 (file)
@@ -232,6 +232,9 @@ void g_leave (void);
 
 
 
+void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes);
+/* Swap a register variable with a location on the stack */
+
 void g_save_regvars (int RegOffs, unsigned Bytes);
 /* Save register variables */
 
index dae3cd0e418a1163e77ca4569465ce60326cfbf8..cf04baf9c3a39808af1ce192f12441896b37e20c 100644 (file)
@@ -165,6 +165,9 @@ static const FuncInfo FuncInfoTable[] = {
     { "pushw0sp",              REG_NONE,             REG_AXY                        },
     { "pushwidx",              REG_AXY,              REG_AXY | REG_PTR1             },
     { "pushwysp",              REG_Y,                REG_AXY                        },
+    { "regswap",        REG_AXY,              REG_AXY | REG_TMP1             },
+    { "regswap1",       REG_XY,               REG_A                          },
+    { "regswap2",       REG_XY,               REG_A | REG_Y                  },
     { "shlax1",         REG_AX,                      REG_AX | REG_TMP1              },
     { "shlax2",         REG_AX,                      REG_AX | REG_TMP1              },
     { "shlax3",         REG_AX,                      REG_AX | REG_TMP1              },
index ab500eee2ee1cdab913f89cad3797335d7d940dd..06260ff3a30c71488968d6afb10057237ab69c7c 100644 (file)
@@ -1391,19 +1391,22 @@ void CS_GenRegInfo (CodeSeg* S)
                        break;
                    }
                    if (J->RI->Out2.RegA != Regs.RegA) {
-                       Regs.RegA = -1;
+                       Regs.RegA = UNKNOWN_REGVAL;
                    }
                    if (J->RI->Out2.RegX != Regs.RegX) {
-                       Regs.RegX = -1;
+                       Regs.RegX = UNKNOWN_REGVAL;
                    }
                    if (J->RI->Out2.RegY != Regs.RegY) {
-                       Regs.RegY = -1;
+                       Regs.RegY = UNKNOWN_REGVAL;
                    }
                    if (J->RI->Out2.SRegLo != Regs.SRegLo) {
-                       Regs.SRegLo = -1;
+                       Regs.SRegLo = UNKNOWN_REGVAL;
                    }
                    if (J->RI->Out2.SRegHi != Regs.SRegHi) {
-                       Regs.SRegHi = -1;
+                       Regs.SRegHi = UNKNOWN_REGVAL;
+                   }
+                           if (J->RI->Out2.Tmp1 != Regs.Tmp1) {
+                       Regs.Tmp1 = UNKNOWN_REGVAL;
                    }
                    ++Entry;
                }
index 3a11a9c6a71abdfe88fe996fb1ed876188a310f5..31beea9cfc2d7e31253145e22cd8a75a1918e874 100644 (file)
@@ -288,7 +288,7 @@ unsigned OptAdd3 (CodeSeg* S)
  *
  *     jsr     pushax
  *      lda     xxx
- *     ldy     yyy
+ *             ldx     yyy
  *      jsr     tosaddax
  *
  * and replace it by
index accf3d831d23a224cd8c02ac08c80bb6be8c0c5a..0791afbf816a4f9e4fcbefc70604d626ca3e2062 100644 (file)
@@ -101,7 +101,7 @@ unsigned OptAdd3 (CodeSeg* S);
  *
  *     jsr     pushax
  *      lda     xxx
- *     ldy     yyy
+ *             ldx     yyy
  *      jsr     tosaddax
  *
  * and replace it by
@@ -113,7 +113,7 @@ unsigned OptAdd3 (CodeSeg* S);
  *      adc     yyy
  *      tax
  *      pla
- */                           
+ */
 
 unsigned OptAdd4 (CodeSeg* S);
 /* Search for the sequence
index ed51fe1306b859d4a40900ac54312369fdd105fb..7686a7e70aa35c68e6a2224c4c000d99cb051116 100644 (file)
@@ -34,6 +34,7 @@
 
 
 #include <stdlib.h>
+#include <ctype.h>
 
 /* cc65 */
 #include "codeent.h"
@@ -66,7 +67,7 @@ struct StackOpData {
 
 /* Flags returned by DirectOp */
 #define OP_DIRECT       0x01            /* Direct op may be used */
-#define OP_ONSTACK      0x02            /* Operand is on stack */
+#define OP_RELOAD_Y     0x02            /* Must reload index register Y */
 
 
 
@@ -207,11 +208,9 @@ static void CheckDirectOp (StackOpData* D)
         if (E->AM == AM65_IMM || E->AM == AM65_ZP || E->AM == AM65_ABS) {
             /* These insns are all ok and replaceable */
             D->Flags |= OP_DIRECT;
-        } else if (E->AM == AM65_ZP_INDY          &&
-                   RegValIsKnown (E->RI->In.RegY) &&
-                          (E->Use & REG_SP) != 0) {
-            /* Load from stack with known offset is also ok */
-            D->Flags |= (OP_DIRECT | OP_ONSTACK);
+        } else if (E->AM == AM65_ZP_INDY && RegValIsKnown (E->RI->In.RegY)) {
+            /* Load indirect with known offset is also ok */
+            D->Flags |= (OP_DIRECT | OP_RELOAD_Y);
         }
     }
 }
@@ -222,7 +221,7 @@ static void ReplacePushByStore (StackOpData* D)
 /* Replace the call to the push subroutine by a store into the zero page
  * location (actually, the push is not replaced, because we need it for
  * later, but the name is still ok since the push will get removed at the
- * end of each routine.
+ * end of each routine).
  */
 {
     CodeEntry* X;
@@ -240,7 +239,7 @@ static void ReplacePushByStore (StackOpData* D)
 
 static void AddOpLow (StackOpData* D, opc_t OPC)
 /* Add an op for the low byte of an operator. This function honours the
- * OP_DIRECT and OP_ONSTACK flags and generates the necessary instructions.
+ * OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions.
  * All code is inserted at the current insertion point.
  */
 {
@@ -250,7 +249,7 @@ static void AddOpLow (StackOpData* D, opc_t OPC)
                /* Op with a variable location. If the location is on the stack, we
          * need to reload the Y register.
          */
-        if ((D->Flags & OP_ONSTACK) != 0) {
+        if ((D->Flags & OP_RELOAD_Y) != 0) {
             const char* Arg = MakeHexArg (D->PrevEntry->RI->In.RegY);
             X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI);
             InsertEntry (D, X, D->IP++);
@@ -297,6 +296,33 @@ static void RemovePushAndOp (StackOpData* D)
 
 
 
+static const char* IsRegVar (const StackOpData* D)
+/* If the value pushed is that of a register variable, return the name of the
+ * entry in the register bank. Otherwise return NULL.
+ */
+{
+    CodeEntry* P;
+
+    if (D->PushIndex >= 2                                &&
+        (P = D->PrevEntry) != 0                          &&
+        P->OPC == OP65_LDX                               &&
+        P->AM == AM65_ZP                                 &&
+        strncmp (P->Arg, "regbank+", 7) == 0             &&
+        isdigit (P->Arg[8])                              &&
+        (P = CS_GetEntry (D->Code, D->PushIndex-2)) != 0 &&
+        P->OPC == OP65_LDA                               &&
+        P->AM == AM65_ZP                                 &&
+        strncmp (P->Arg, "regbank+", 7) == 0             &&
+        isdigit (P->Arg[8])) {
+        /* Ok, it loads the register variable */
+        return P->Arg;
+    } else {
+        return 0;
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                      Actual optimization functions                       */
 /*****************************************************************************/
@@ -307,12 +333,20 @@ static unsigned Opt_staspidx (StackOpData* D)
 /* Optimize the staspidx sequence if possible */
 {
     CodeEntry* X;
+    const char* ZPLo;
 
-    /* Store the value into the zeropage instead of pushing it */
-    ReplacePushByStore (D);
+    /* Check if we're using a register variable */
+    if ((ZPLo = IsRegVar (D)) == 0) {
+
+        /* Store the value into the zeropage instead of pushing it */
+        ReplacePushByStore (D);
+
+        /* Use the given zero page loc */
+        ZPLo = D->ZPLo;
+    }
 
     /* Replace the store subroutine call by a direct op */
-    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI);
+    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, D->OpEntry->LI);
     InsertEntry (D, X, D->OpIndex+1);
 
     /* Remove the push and the call to the staspidx function */
@@ -328,12 +362,20 @@ static unsigned Opt_staxspidx (StackOpData* D)
 /* Optimize the staxspidx sequence if possible */
 {
     CodeEntry* X;
+    const char* ZPLo;
 
-    /* Store the value into the zeropage instead of pushing it */
-    ReplacePushByStore (D);
+    /* Check if we're using a register variable */
+    if ((ZPLo = IsRegVar (D)) == 0) {
+
+        /* Store the value into the zeropage instead of pushing it */
+        ReplacePushByStore (D);
+
+        /* Use the given zero page loc */
+        ZPLo = D->ZPLo;
+    }
 
     /* Inline the store */
-    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI);
+    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, D->OpEntry->LI);
     InsertEntry (D, X, D->OpIndex+1);
     X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, D->OpEntry->LI);
     InsertEntry (D, X, D->OpIndex+2);
@@ -346,7 +388,7 @@ static unsigned Opt_staxspidx (StackOpData* D)
        X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, D->OpEntry->LI);
     }
     InsertEntry (D, X, D->OpIndex+3);
-    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI);
+    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLo, 0, D->OpEntry->LI);
     InsertEntry (D, X, D->OpIndex+4);
 
     /* Remove the push and the call to the staspidx function */
@@ -607,7 +649,7 @@ static int HarmlessCall (const char* Name)
  */
 {
     static const char* Tab[] = {
-        "ldaxidx", 
+        "ldaxidx",
         "ldaxysp",
     };
 
index 0c647c83574a454291a351b02dd50770575ece91..22d8c310ebce22fb82c2a25bfe72b3963965d43f 100644 (file)
@@ -83,7 +83,7 @@ static type OptionalQualifiers (type Q)
        switch (CurTok.Tok) {
 
            case TOK_CONST:
-               if (Q & T_QUAL_CONST) {
+               if (Q & T_QUAL_CONST) {
                    Error ("Duplicate qualifier: `const'");
                }
                Q |= T_QUAL_CONST;
@@ -339,7 +339,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
     ident      Ident;
     SymEntry*  Entry;
     type       StructType;
-    type       Qualifiers;     /* Type qualifiers */
+    type       Qualifiers;     /* Type qualifiers */
 
     /* Assume we have an explicit type */
     D->Flags &= ~DS_DEF_TYPE;
@@ -427,7 +427,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                    /* FALL THROUGH */
 
                default:
-                   D->Type[0] = T_INT;
+                   D->Type[0] = T_INT;
                    D->Type[1] = T_END;
                    break;
            }
@@ -663,14 +663,15 @@ static void ParseAnsiParamList (FuncDesc* F)
        /* Read the declaration specifier */
        ParseDeclSpec (&Spec, SC_AUTO, T_INT);
 
-               /* We accept only auto and register as storage class specifiers, but
-        * we ignore all this and use auto.
-        */
-       if ((Spec.StorageClass & SC_AUTO) == 0 &&
-           (Spec.StorageClass & SC_REGISTER) == 0) {
+               /* We accept only auto and register as storage class specifiers */
+        if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
+            Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
+        } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
+            Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
+        } else {
            Error ("Illegal storage class");
+            Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
        }
-       Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
 
        /* Allow parameters without a name, but remember if we had some to
         * eventually print an error message later.
@@ -755,10 +756,10 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
 
            /* Check for an implicit int return in the K&R function */
            if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
-               Spec->Type[0] == T_INT   &&
-               Spec->Type[1] == T_END) {
-               /* Function has an implicit int return */
-               F->Flags |= FD_OLDSTYLE_INTRET;
+               Spec->Type[0] == T_INT   &&
+               Spec->Type[1] == T_END) {
+               /* Function has an implicit int return */
+               F->Flags |= FD_OLDSTYLE_INTRET;
            }
        }
     }
@@ -779,7 +780,11 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
     Sym = GetSymTab()->SymTail;
     while (Sym) {
        unsigned Size = CheckedSizeOf (Sym->Type);
-       Sym->V.Offs = Offs;
+        if (SymIsRegVar (Sym)) {
+            Sym->V.R.SaveOffs = Offs;
+        } else {
+           Sym->V.Offs = Offs;
+        }
                Offs += Size;
        F->ParamSize += Size;
        Sym = Sym->PrevSym;
index 66777b189e624246bda42449db6ecb241992d70a..edf795b8d6bb514bf314b995d8fdee5859f02597 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2001 Ullrich von Bassewitz                                       */
+/* (C) 2000-2002 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@cc65.org                                                 */
 
 
 
+/* Maximum register variable size */
+#define MAX_REG_SPACE   6
+
 /* Structure that holds all data needed for function activation */
 struct Function {
-    struct SymEntry*           FuncEntry;      /* Symbol table entry */
-    type*              ReturnType;     /* Function return type */
-    struct FuncDesc*   Desc;           /* Function descriptor */
-    int                        Reserved;       /* Reserved local space */
+    struct SymEntry*           FuncEntry;      /* Symbol table entry */
+    type*              ReturnType;     /* Function return type */
+    struct FuncDesc*   Desc;           /* Function descriptor */
+    int                        Reserved;       /* Reserved local space */
     unsigned           RetLab;         /* Return code label */
     int                        TopLevelSP;     /* SP at function top level */
+    unsigned            RegOffs;        /* Register variable space offset */
 };
 
 /* Pointer to current function */
@@ -94,6 +98,7 @@ static Function* NewFunction (struct SymEntry* Sym)
     F->Reserved          = 0;
     F->RetLab    = GetLocalLabel ();
     F->TopLevelSP = 0;
+    F->RegOffs    = MAX_REG_SPACE;
 
     /* Return the new structure */
     return F;
@@ -220,6 +225,108 @@ void F_AllocLocalSpace (Function* F)
 
 
 
+int F_AllocRegVar (Function* F, const type* Type)
+/* Allocate a register variable for the given variable type. If the allocation
+ * was successful, return the offset of the register variable in the register
+ * bank (zero page storage). If there is no register space left, return -1.
+ */
+{
+    /* Allow register variables only on top level and if enabled */
+    if (EnableRegVars && GetLexicalLevel () == LEX_LEVEL_FUNCTION) {
+
+       /* Get the size of the variable */
+       unsigned Size = CheckedSizeOf (Type);
+
+       /* Do we have space left? */
+       if (F->RegOffs >= Size) {
+           /* Space left. We allocate the variables from high to low addresses,
+            * so the adressing is compatible with the saved values on stack.
+            * This allows shorter code when saving/restoring the variables.
+            */
+           F->RegOffs -= Size;
+           return F->RegOffs;
+       }
+    }
+
+    /* No space left or no allocation */
+    return -1;
+}
+
+
+
+static void F_RestoreRegVars (Function* F)
+/* Restore the register variables for the local function if there are any. */
+{
+    const SymEntry* Sym;
+
+    /* If we don't have register variables in this function, bail out early */
+    if (F->RegOffs == MAX_REG_SPACE) {
+               return;
+    }
+
+    /* Save the accumulator if needed */
+    if (!F_HasVoidReturn (F)) {
+               g_save (CF_CHAR | CF_FORCECHAR);
+    }
+
+    /* Get the first symbol from the function symbol table */
+    Sym = F->FuncEntry->V.F.Func->SymTab->SymHead;
+
+    /* Walk through all symbols checking for register variables */
+    while (Sym) {
+        if (SymIsRegVar (Sym)) {
+
+            /* Check for more than one variable */
+            int Offs       = Sym->V.R.SaveOffs;
+            unsigned Bytes = CheckedSizeOf (Sym->Type);
+
+            while (1) {
+
+                /* Find next register variable */
+                const SymEntry* NextSym = Sym->NextSym;
+                while (NextSym && !SymIsRegVar (NextSym)) {
+                    NextSym = NextSym->NextSym;
+                }
+
+                /* If we have a next one, compare the stack offsets */
+                if (NextSym) {
+
+                    /* We have a following register variable. Get the size */
+                    int Size = CheckedSizeOf (NextSym->Type);
+
+                    /* Adjacent variable? */
+                    if (NextSym->V.R.SaveOffs + Size != Offs) {
+                        /* No */
+                        break;
+                    }
+
+                    /* Adjacent variable */
+                    Bytes += Size;
+                    Offs  -= Size;
+                    Sym   = NextSym;
+
+                } else {
+                    break;
+                }
+            }
+
+            /* Restore the memory range */
+            g_restore_regvars (Offs, Sym->V.R.RegOffs, Bytes);
+
+        }
+
+        /* Check next symbol */
+        Sym = Sym->NextSym;
+    }
+
+    /* Restore the accumulator if needed */
+    if (!F_HasVoidReturn (F)) {
+       g_restore (CF_CHAR | CF_FORCECHAR);
+    }
+}
+
+
+
 /*****************************************************************************/
 /*                                          code                                    */
 /*****************************************************************************/
@@ -230,8 +337,8 @@ void NewFunc (SymEntry* Func)
 /* Parse argument declarations and function body. */
 {
     int HadReturn;
-    int IsVoidFunc;
     SymEntry* LastParam;
+    SymEntry* Param;
 
     /* Get the function descriptor from the function entry */
     FuncDesc* D = Func->V.F.Func;
@@ -262,9 +369,6 @@ void NewFunc (SymEntry* Func)
     /* Function body now defined */
     Func->Flags |= SC_DEF;
 
-    /* Setup register variables */
-    InitRegVars ();
-
     /* Allocate code and data segments for this function */
     Func->V.F.Seg = PushSegments (Func);
 
@@ -281,18 +385,49 @@ void NewFunc (SymEntry* Func)
            /* Pointer to function */
            Flags = CF_PTR;
        } else {
-           Flags = TypeOf (LastParam->Type) | CF_FORCECHAR;
+           Flags = TypeOf (LastParam->Type) | CF_FORCECHAR;
        }
        g_push (Flags, 0);
     }
 
+    /* Generate function entry code if needed */
+    g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc));
+
     /* If stack checking code is requested, emit a call to the helper routine */
     if (CheckStack) {
-       g_stackcheck ();
+       g_stackcheck ();
     }
 
-    /* Generate function entry code if needed */
-    g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc));
+    /* Walk through the parameter list and allocate register variable space
+     * for parameters declared as register. Generate code to swap the contents
+     * of the register bank with the save area on the stack.
+     */
+    Param = D->SymTab->SymHead;
+    while (Param && (Param->Flags & SC_PARAM) != 0) {
+
+        /* Check for a register variable */
+        if (SymIsRegVar (Param)) {
+
+            /* Allocate space */
+            int Reg = F_AllocRegVar (CurrentFunc, Param->Type);
+
+            /* Could we allocate a register? */
+            if (Reg < 0) {
+                /* No register available: Convert parameter to auto */
+                CvtRegVarToAuto (Param);
+            } else {
+                /* Remember the register offset */
+                Param->V.R.RegOffs = Reg;
+
+                /* Generate swap code */
+                g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (Param->Type));
+
+            }
+        }
+
+        /* Next parameter */
+        Param = Param->NextSym;
+    }
 
     /* Setup the stack */
     oursp = 0;
@@ -318,22 +453,11 @@ void NewFunc (SymEntry* Func)
        }
     }
 
-    /* If the function has a return type but no return statement, flag
-     * a warning
-     */
-    IsVoidFunc = F_HasVoidReturn (CurrentFunc);
-#if 0
-    /* Does not work reliably */
-    if (!F_IsVoidFunc && !HadReturn) {
-       Warning ("Function `%s' should return a value", Func->Name);
-    }
-#endif
-
     /* Output the function exit code label */
     g_defcodelabel (F_GetRetLab (CurrentFunc));
 
     /* Restore the register variables */
-    RestoreRegVars (!IsVoidFunc);
+    F_RestoreRegVars (CurrentFunc);
 
     /* Generate the exit code */
     g_leave ();
@@ -344,9 +468,6 @@ void NewFunc (SymEntry* Func)
     /* Emit references to imports/exports */
     EmitExternals ();
 
-    /* Cleanup register variables */
-    DoneRegVars ();
-
     /* Leave the lexical level */
     LeaveFunctionLevel ();
 
index 56e532179e3aab1e74ff80e3cad68c4921e19bc6..70f3dd2ed8891a1229033b860bb6aca916377ae9 100644 (file)
@@ -98,6 +98,12 @@ void F_AllocLocalSpace (Function* F);
  * nothing if there is no reserved local space.
  */
 
+int F_AllocRegVar (Function* F, const type* Type);
+/* Allocate a register variable for the given variable type. If the allocation
+ * was successful, return the offset of the register variable in the register
+ * bank (zero page storage). If there is no register space left, return -1.
+ */
+
 void NewFunc (struct SymEntry* Func);
 /* Parse argument declarations and function body. */
 
index ad87c3ebd75006b1ee87ffa7fdbc37e7e251533a..a4411e410fd8b0e982a176f96ff6a5d464619199 100644 (file)
 
 
 
-/*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Register variable management */
-unsigned MaxRegSpace           = 6;    /* Maximum space available */
-static unsigned RegOffs        = 0;    /* Offset into register space */
-static const SymEntry** RegSyms        = 0;    /* The register variables */
-static unsigned RegSymCount    = 0;    /* Number of register variables */
-
-
-
 /*****************************************************************************/
 /*                                  Code                                    */
 /*****************************************************************************/
 
 
 
-void InitRegVars (void)
-/* Initialize register variable control data */
-{
-    /* If the register space is zero, bail out */
-    if (MaxRegSpace == 0) {
-               return;
-    }
-
-    /* The maximum number of register variables is equal to the register
-     * variable space available. So allocate one pointer per byte. This
-     * will usually waste some space but we don't need to dynamically
-     * grow the array.
-     */
-    RegSyms = (const SymEntry**) xmalloc (MaxRegSpace * sizeof (RegSyms[0]));
-    RegOffs = MaxRegSpace;
-}
-
-
-
-void DoneRegVars (void)
-/* Free the register variables */
-{
-    xfree (RegSyms);
-    RegSyms = 0;
-    RegOffs = MaxRegSpace;
-    RegSymCount = 0;
-}
-
-
-
-static int AllocRegVar (const type* Type)
-/* Allocate a register variable for the given variable type. If the allocation
- * was successful, return the offset of the register variable in the register
- * bank (zero page storage). If there is no register space left, return -1.
- */
-{
-    /* Maybe register variables are disabled... */
-    if (EnableRegVars) {
-
-       /* Get the size of the variable */
-       unsigned Size = CheckedSizeOf (Type);
-
-       /* Do we have space left? */
-       if (RegOffs >= Size) {
-           /* Space left. We allocate the variables from high to low addresses,
-            * so the adressing is compatible with the saved values on stack.
-            * This allows shorter code when saving/restoring the variables.
-            */
-           RegOffs -= Size;
-           return RegOffs;
-       }
-    }
-
-    /* No space left or no allocation */
-    return -1;
-}
-
-
-
-static void RememberRegVar (const SymEntry* Sym)
-/* Remember the given register variable */
-{
-    RegSyms[RegSymCount++] = Sym;
-}
-
-
-
 static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
 /* Parse the declaration of a register variable. The function returns the
  * symbol data, which is the offset of the variable in the register bank.
@@ -185,7 +104,7 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
         } else {
 
             /* Setup the type flags for the assignment */
-            Flags = CF_REGVAR;
+            Flags = CF_NONE;
             if (Size == SIZEOF_CHAR) {
                 Flags |= CF_FORCECHAR;
             }
@@ -195,12 +114,15 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
                 /* Constant expression. Adjust the types */
                 assignadjust (Decl->Type, &lval);
                 Flags |= CF_CONST;
+                /* Load it into the primary */
+                exprhs (Flags, 0, &lval);
             } else {
                 /* Expression is not constant and in the primary */
                 assignadjust (Decl->Type, &lval);
             }
 
             /* Store the value into the variable */
+            Flags |= CF_REGVAR;
             g_putstatic (Flags | TypeOf (Decl->Type), Reg, 0);
 
         }
@@ -456,7 +378,6 @@ static void ParseOneDecl (const DeclSpec* Spec)
     unsigned    SC;            /* Storage class for symbol */
     unsigned    SymData = 0;    /* Symbol data (offset, label name, ...) */
     Declaration Decl;          /* Declaration data structure */
-    SymEntry*   Sym;            /* Symbol declared */
 
 
     /* Remember the storage class for the new symbol */
@@ -467,10 +388,10 @@ static void ParseOneDecl (const DeclSpec* Spec)
 
     /* Set the correct storage class for functions */
     if (IsTypeFunc (Decl.Type)) {
-       /* Function prototypes are always external */
-       if ((SC & SC_EXTERN) == 0) {
+       /* Function prototypes are always external */
+       if ((SC & SC_EXTERN) == 0) {
                    Warning ("Function must be extern");
-       }
+       }
                SC |= SC_FUNC | SC_EXTERN;
 
     }
@@ -489,19 +410,19 @@ static void ParseOneDecl (const DeclSpec* Spec)
          * convert the declaration to "auto" if this is not possible.
          */
         int Reg = 0;    /* Initialize to avoid gcc complains */
-        if ((SC & SC_REGISTER) != 0 && (Reg = AllocRegVar (Decl.Type)) < 0) {
+        if ((SC & SC_REGISTER) != 0 && (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) {
             /* No space for this register variable, convert to auto */
             SC = (SC & ~SC_REGISTER) | SC_AUTO;
         }
 
         /* Check the variable type */
-        if (SC & SC_REGISTER) {
+        if ((SC & SC_REGISTER) == SC_REGISTER) {
             /* Register variable */
             SymData = ParseRegisterDecl (&Decl, &SC, Reg);
-               } else if (SC & SC_AUTO) {
+               } else if ((SC & SC_AUTO) == SC_AUTO) {
             /* Auto variable */
             SymData = ParseAutoDecl (&Decl, &SC);
-               } else if (SC & SC_STATIC) {
+               } else if ((SC & SC_STATIC) == SC_STATIC) {
             /* Static variable */
             SymData = ParseStaticDecl (&Decl, &SC);
                } else {
@@ -515,12 +436,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
     }
 
     /* Add the symbol to the symbol table */
-    Sym = AddLocalSym (Decl.Ident, Decl.Type, SC, SymData);
-
-    /* If we had declared a register variable, remember it now */
-    if (SC & SC_REGISTER) {
-        RememberRegVar (Sym);
-    }
+    AddLocalSym (Decl.Ident, Decl.Type, SC, SymData);
 }
 
 
@@ -587,70 +503,3 @@ void DeclareLocals (void)
 
 
 
-void RestoreRegVars (int HaveResult)
-/* Restore the register variables for the local function if there are any.
- * The parameter tells us if there is a return value in ax, in that case,
- * the accumulator must be saved across the restore.
- */
-{
-    unsigned I, J;
-    int Bytes, Offs;
-
-    /* If we don't have register variables in this function, bail out early */
-    if (RegSymCount == 0) {
-       return;
-    }
-
-    /* Save the accumulator if needed */
-    if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
-       g_save (CF_CHAR | CF_FORCECHAR);
-    }
-
-    /* Walk through all variables. If there are several variables in a row
-     * (that is, with increasing stack offset), restore them in one chunk.
-     */
-    I = 0;
-    while (I < RegSymCount) {
-
-       /* Check for more than one variable */
-               const SymEntry* Sym = RegSyms[I];    
-       Offs  = Sym->V.R.SaveOffs;
-       Bytes = CheckedSizeOf (Sym->Type);
-       J = I+1;
-
-               while (J < RegSymCount) {
-
-           /* Get the next symbol */
-           const SymEntry* NextSym = RegSyms [J];
-
-           /* Get the size */
-           int Size = CheckedSizeOf (NextSym->Type);
-
-           /* Adjacent variable? */
-           if (NextSym->V.R.SaveOffs + Size != Offs) {
-               /* No */
-               break;
-           }
-
-           /* Adjacent variable */
-           Bytes += Size;
-           Offs  -= Size;
-           Sym   = NextSym;
-           ++J;
-       }
-
-       /* Restore the memory range */
-               g_restore_regvars (Offs, Sym->V.R.RegOffs, Bytes);
-
-       /* Next round */
-       I = J;
-    }
-
-    /* Restore the accumulator if needed */
-    if (!F_HasVoidReturn (CurrentFunc) && HaveResult) {
-       g_restore (CF_CHAR | CF_FORCECHAR);
-    }
-}
-
-
-
index e50c3558196964a51cca9ae720d567efa5fd433e..8de716ddfb77f0083d96239a253d40032b1ae33a 100644 (file)
 void RC_Invalidate (RegContents* C)
 /* Invalidate all registers */
 {
-    C->RegA   = -1;
-    C->RegX   = -1;
-    C->RegY   = -1;
-    C->SRegLo = -1;
-    C->SRegHi = -1;
-    C->Tmp1   = -1;
+    C->RegA   = UNKNOWN_REGVAL;
+    C->RegX   = UNKNOWN_REGVAL;
+    C->RegY   = UNKNOWN_REGVAL;
+    C->SRegLo = UNKNOWN_REGVAL;
+    C->SRegHi = UNKNOWN_REGVAL;
+    C->Tmp1   = UNKNOWN_REGVAL;
 }
 
 
@@ -63,9 +63,9 @@ void RC_Invalidate (RegContents* C)
 void RC_InvalidateZP (RegContents* C)
 /* Invalidate all ZP registers */
 {
-    C->SRegLo = -1;
-    C->SRegHi = -1;
-    C->Tmp1   = -1;
+    C->SRegLo = UNKNOWN_REGVAL;
+    C->SRegHi = UNKNOWN_REGVAL;
+    C->Tmp1   = UNKNOWN_REGVAL;
 }
 
 
@@ -104,4 +104,4 @@ void FreeRegInfo (RegInfo* RI)
 
 
 
-                  
+
index ecfe08a70d986e3ad2f1685320f4c9b1461c29ad..ad49043d357683a56bfb48fbb34be126c6c62e44 100644 (file)
@@ -49,6 +49,9 @@
 
 
 
+/* Encoding for an unknown register value */
+#define UNKNOWN_REGVAL  -1
+
 /* Register contents */
 typedef struct RegContents RegContents;
 struct RegContents {
index 6745680d3820278bfa53931cd26a3dbabdaa3f09..bac584becfdb56aed0262a335d4bb3d617cc347f 100644 (file)
@@ -149,6 +149,18 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
 
 
 
+void CvtRegVarToAuto (SymEntry* Sym)
+/* Convert a register variable to an auto variable */
+{
+    /* Change the storage class */
+    Sym->Flags = (Sym->Flags & ~(SC_REGISTER | SC_STATIC | SC_EXTERN)) | SC_AUTO;
+
+    /* Transfer the stack offset from register save area to actual offset */
+    Sym->V.Offs = Sym->V.R.SaveOffs;
+}
+
+
+
 void ChangeSymType (SymEntry* Entry, type* Type)
 /* Change the type of the given symbol */
 {
index e81945d648da806c30f0fd91c3448981c4395e0b..b1f8647035d0de46ebe2f0c7d269d708e86f1de5 100644 (file)
@@ -186,6 +186,19 @@ INLINE int SymIsRef (const SymEntry* Sym)
 #  define SymIsRef(Sym)     (((Sym)->Flags & SC_REF) == SC_REF)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE int SymIsRegVar (const SymEntry* Sym)
+/* Return true if the given entry is a register variable */
+{
+    return ((Sym->Flags & SC_REGISTER) == SC_REGISTER);
+}
+#else
+#  define SymIsRegVar(Sym)      (((Sym)->Flags & SC_REGISTER) == SC_REGISTER)
+#endif
+
+void CvtRegVarToAuto (SymEntry* Sym);
+/* Convert a register variable to an auto variable */
+
 void ChangeSymType (SymEntry* Entry, type* Type);
 /* Change the type of the given symbol */
 
index 988190cd6a50a462790cde0a3c29433774e63bcb..850725be9a97b83c263ce60dcffd295bc1c99349 100644 (file)
@@ -81,9 +81,6 @@ SymTable      EmptySymTab = {
 #define SYMTAB_SIZE_STRUCT      19U
 #define SYMTAB_SIZE_LABEL        7U
 
-/* Predefined lexical levels */
-#define LEX_LEVEL_GLOBAL       1U
-
 /* The current and root symbol tables */
 static unsigned                LexicalLevel    = 0;    /* For safety checks */
 static SymTable*       SymTab0         = 0;
@@ -198,6 +195,14 @@ static void CheckSymTable (SymTable* Tab)
 
 
 
+unsigned GetLexicalLevel (void)
+/* Return the current lexical level */
+{
+    return LexicalLevel;
+}
+
+
+
 void EnterGlobalLevel (void)
 /* Enter the program global lexical level */
 {
@@ -241,7 +246,7 @@ void EnterFunctionLevel (void)
     SymTable* S;
 
     /* New lexical level */
-    ++LexicalLevel;
+    PRECONDITION (++LexicalLevel == LEX_LEVEL_FUNCTION);
 
     /* Get a new symbol table and make it current */
     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
@@ -263,7 +268,7 @@ void RememberFunctionLevel (struct FuncDesc* F)
 /* Remember the symbol tables for the level and leave the level without checks */
 {
     /* Leave the lexical level */
-    --LexicalLevel;
+    PRECONDITION (LexicalLevel-- == LEX_LEVEL_FUNCTION);
 
     /* Remember the tables */
     F->SymTab = SymTab;
@@ -280,7 +285,7 @@ void ReenterFunctionLevel (struct FuncDesc* F)
 /* Reenter the function lexical level using the existing tables from F */
 {
     /* New lexical level */
-    ++LexicalLevel;
+    PRECONDITION (++LexicalLevel == LEX_LEVEL_FUNCTION);
 
     /* Make the tables current again */
     F->SymTab->PrevTab = SymTab;
@@ -299,7 +304,7 @@ void LeaveFunctionLevel (void)
 /* Leave function lexical level */
 {
     /* Leave the lexical level */
-    --LexicalLevel;
+    PRECONDITION (LexicalLevel-- == LEX_LEVEL_FUNCTION);
 
     /* Check the tables */
     CheckSymTable (SymTab);
index 317d8f8b808682958e27c5418190da679cb55fdd..5321ac07b88ea5aecddbffa57a5fc902cc04be74 100644 (file)
@@ -68,6 +68,10 @@ extern SymTable              EmptySymTab;
 /* Forwards */
 struct FuncDesc;
 
+/* Predefined lexical levels */
+#define LEX_LEVEL_GLOBAL       1U
+#define LEX_LEVEL_FUNCTION      2U
+
 
 
 /*****************************************************************************/
@@ -76,6 +80,9 @@ struct FuncDesc;
 
 
 
+unsigned GetLexicalLevel (void);
+/* Return the current lexical level */
+
 void EnterGlobalLevel (void);
 /* Enter the program global lexical level */