]> git.sur5r.net Git - cc65/commitdiff
Move shift expression evaluation into a separate module. More checks and
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 29 Jun 2004 20:44:01 +0000 (20:44 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 29 Jun 2004 20:44:01 +0000 (20:44 +0000)
improvements for shift expressions.

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

src/cc65/expr.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/shiftexpr.c [new file with mode: 0644]
src/cc65/shiftexpr.h [new file with mode: 0644]

index 6cd41138b33bf2021beca923d0d09761730a1526..ca5db3db13e2accb10a80cf6e4376c2f75330c13 100644 (file)
@@ -29,6 +29,7 @@
 #include "macrotab.h"
 #include "preproc.h"
 #include "scanner.h"
+#include "shiftexpr.h"
 #include "stackptr.h"
 #include "stdfunc.h"
 #include "symtab.h"
@@ -86,7 +87,7 @@ static unsigned GlobalModeFlags (unsigned Flags)
     }
 }
 
-             
+
 
 void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr)
 /* Call an expression function with checks. */
@@ -2281,196 +2282,6 @@ void hie8 (ExprDesc* Expr)
 
 
 
-static void hie7 (ExprDesc* Expr)
-/* Parse the << and >> operators. */
-{
-    ExprDesc Expr2;
-    CodeMark Mark1;
-    CodeMark Mark2;
-    token_t Tok;                               /* The operator token */
-    unsigned ltype, rtype, flags;
-    int rconst;                                /* Operand is a constant */
-
-
-    /* Evaluate the lhs */
-    ExprWithCheck (hie8, Expr);
-
-    while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
-
-       /* All operators that call this function expect an int on the lhs */
-       if (!IsClassInt (Expr->Type)) {
-           Error ("Integer expression expected");
-            ED_MakeConstAbsInt (Expr, 1);
-       }
-
-       /* Remember the operator token, then skip it */
-               Tok = CurTok.Tok;
-       NextToken ();
-
-       /* Get the lhs on stack */
-               Mark1 = GetCodePos ();
-       ltype = TypeOf (Expr->Type);
-               if (ED_IsConstAbs (Expr)) {
-           /* Constant value */
-           Mark2 = GetCodePos ();
-                   g_push (ltype | CF_CONST, Expr->IVal);
-       } else {
-           /* Value not constant */
-           LoadExpr (CF_NONE, Expr);
-           Mark2 = GetCodePos ();
-           g_push (ltype, 0);
-       }
-
-       /* Get the right hand side */
-        ExprWithCheck (hie8, &Expr2);
-
-       /* Check the type of the rhs */
-       if (!IsClassInt (Expr2.Type)) {
-           Error ("Integer expression expected");
-            ED_MakeConstAbsInt (&Expr2, 1);
-       }
-
-        /* Check for a constant right side expression */
-        rconst = ED_IsConstAbs (&Expr2);
-        if (!rconst) {
-
-            /* Not constant, load into the primary */
-            LoadExpr (CF_NONE, &Expr2);
-
-        } else {
-
-            /* If the right hand side is constant, we can check a lot of
-             * things:
-             */
-
-            /* If the shift count is zero, nothing happens */
-            if (Expr2.IVal == 0) {
-
-                /* Result is already in Expr, remove the generated code */
-                RemoveCode (Mark1);
-                pop (ltype);
-
-                /* Done */
-                goto Next;
-            }
-
-            /* If the left hand side is a constant, the result is constant */
-            if (ED_IsConstAbs (Expr)) {
-
-                /* Evaluate the result */
-                Expr->IVal = kcalc (Tok, Expr->IVal, Expr2.IVal);
-
-                /* Both operands are constant, remove the generated code */
-                RemoveCode (Mark1);
-                pop (ltype);
-
-                /* Done */
-                goto Next;
-            }
-
-            /* If we're shifting to the left, and the shift count is larger
-             * or equal than the bit count of the integer type, the result
-             * is zero.
-             */
-            if (Tok == TOK_SHL && Expr2.IVal >= (long) SizeOf (Expr->Type) * 8) {
-
-                /* Set the result */
-                ED_MakeConstAbs (Expr, 0, Expr->Type);
-
-                /* Result is zero, remove the generated code */
-                RemoveCode (Mark1);
-                pop (ltype);
-
-                /* Done */
-                goto Next;
-            }
-
-            /* If we're shifting an integer or unsigned to the right, the
-             * lhs has a const address, and the shift count is larger than 8,
-             * we can load just the high byte as a char with the correct
-             * signedness, and reduce the shift count by 8. If the remaining
-             * shift count is zero, we're done.
-             */
-            if (Tok == TOK_SHR &&
-                IsTypeInt (Expr->Type) &&
-                ED_IsLVal (Expr) &&
-                (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) &&
-                Expr2.IVal >= 8) {
-
-                type* OldType;
-
-                /* Increase the address by one and decrease the shift count */
-                ++Expr->IVal;
-                Expr2.IVal -= 8;
-
-                /* Replace the type of the expression temporarily by the
-                 * corresponding char type.
-                 */
-                OldType = Expr->Type;
-                if (IsSignUnsigned (Expr->Type)) {
-                    Expr->Type = type_uchar;
-                } else {
-                    Expr->Type = type_schar;
-                }
-
-                /* Remove the generated load code */
-                RemoveCode (Mark1);
-                pop (ltype);
-
-                /* Generate again code for the load */
-                LoadExpr (CF_NONE, Expr);
-
-                /* Reset the type */
-                Expr->Type = OldType;
-
-                /* If the shift count is now zero, we're done */
-                if (Expr2.IVal == 0) {
-                    /* Be sure to mark the value as in the primary */
-                    goto Loaded;
-                }
-
-                /* Otherwise generate code to push the value */
-                Mark2 = GetCodePos ();
-                g_push (ltype, 0);
-            }
-
-        }
-
-        /* If the right hand side is a constant, remove the push of the
-         * primary register.
-         */
-        rtype = TypeOf (Expr2.Type);
-        flags = 0;
-        if (rconst) {
-            flags |= CF_CONST;
-            rtype |= CF_CONST;
-            RemoveCode (Mark2);
-            pop (ltype);
-            ltype |= CF_REG;           /* Value is in register */
-        }
-
-        /* Determine the type of the operation result. */
-        flags |= g_typeadjust (ltype, rtype);
-
-        /* Generate code */
-        switch (Tok) {
-            case TOK_SHL: g_asl (flags, Expr2.IVal); break;
-            case TOK_SHR: g_asr (flags, Expr2.IVal); break;
-            default:                                 break;
-        }
-
-Loaded:
-        /* We have a rvalue in the primary now */
-        ED_MakeRValExpr (Expr);
-
-Next:
-        /* Get the type of the result */
-       Expr->Type = promoteint (Expr->Type, Expr2.Type);
-    }
-}
-
-
-
 static void hie6 (ExprDesc* Expr)
 /* Handle greater-than type comparators */
 {
@@ -2481,7 +2292,7 @@ static void hie6 (ExprDesc* Expr)
         { TOK_GT,      GEN_NOPUSH,     g_gt    },
         { TOK_INVALID,  0,              0       }
     };
-    hie_compare (hie6_ops, Expr, hie7);
+    hie_compare (hie6_ops, Expr, ShiftExpr);
 }
 
 
index 46c8ce258eb14c38d02cc212a8abc8f3eae1ae2b..5f672934efdb940d737510d18186156fcfa3b4e6 100644 (file)
@@ -78,6 +78,7 @@ OBJS =        anonname.o      \
        scanner.o       \
         scanstrbuf.o    \
        segments.o      \
+        shiftexpr.o     \
         stackptr.o      \
         standard.o      \
        stdfunc.o       \
index 521e669f9066936a2ed0cae91c54db7ac225a31a..789a418438b46f73dc21741a67c0c2cf2eba2967 100644 (file)
@@ -113,6 +113,7 @@ OBJS =      anonname.obj    \
        scanner.obj     \
         scanstrbuf.obj  \
        segments.obj    \
+        shiftexpr.obj   \
         stackptr.obj    \
         standard.obj    \
        stdfunc.obj     \
diff --git a/src/cc65/shiftexpr.c b/src/cc65/shiftexpr.c
new file mode 100644 (file)
index 0000000..9e41109
--- /dev/null
@@ -0,0 +1,250 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                shiftexpr.c                                */
+/*                                                                           */
+/*                       Parse the << and >> operators                       */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2004      Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* cc65 */
+#include "asmcode.h"
+#include "codegen.h"
+#include "datatype.h"
+#include "error.h"
+#include "expr.h"
+#include "exprdesc.h"
+#include "loadexpr.h"
+#include "scanner.h"
+#include "shiftexpr.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+void ShiftExpr (struct ExprDesc* Expr)
+/* Parse the << and >> operators. */
+{
+    ExprDesc Expr2;
+    CodeMark Mark1;
+    CodeMark Mark2;
+    token_t Tok;                               /* The operator token */
+    unsigned ExprBits;                  /* Bits of the lhs operand */
+    unsigned ltype, rtype, flags;
+    int rconst;                                /* Operand is a constant */
+
+
+    /* Evaluate the lhs */
+    ExprWithCheck (hie8, Expr);
+
+    while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
+
+       /* All operators that call this function expect an int on the lhs */
+       if (!IsClassInt (Expr->Type)) {
+           Error ("Integer expression expected");
+            ED_MakeConstAbsInt (Expr, 1);
+       }
+
+       /* Remember the operator token, then skip it */
+               Tok = CurTok.Tok;
+       NextToken ();
+
+        /* Calculate the number of bits the lhs operand has */
+        ExprBits = SizeOf (Expr->Type) * 8;
+
+       /* Get the lhs on stack */
+               Mark1 = GetCodePos ();
+       ltype = TypeOf (Expr->Type);
+               if (ED_IsConstAbs (Expr)) {
+           /* Constant value */
+           Mark2 = GetCodePos ();
+                   g_push (ltype | CF_CONST, Expr->IVal);
+       } else {
+           /* Value not constant */
+           LoadExpr (CF_NONE, Expr);
+           Mark2 = GetCodePos ();
+           g_push (ltype, 0);
+       }
+
+       /* Get the right hand side */
+        ExprWithCheck (hie8, &Expr2);
+
+       /* Check the type of the rhs */
+       if (!IsClassInt (Expr2.Type)) {
+           Error ("Integer expression expected");
+            ED_MakeConstAbsInt (&Expr2, 1);
+       }
+
+        /* Check for a constant right side expression */
+        rconst = ED_IsConstAbs (&Expr2);
+        if (!rconst) {
+
+            /* Not constant, load into the primary */
+            LoadExpr (CF_NONE, &Expr2);
+
+        } else {
+
+            /* The rhs is a constant numeric value */
+
+            /* If the shift count is greater or equal than the bit count of
+             * the operand, the behaviour is undefined according to the
+             * standard.
+             */
+            if (Expr2.IVal < 0 || Expr2.IVal >= (long) ExprBits) {
+
+                Warning ("Shift count too large for operand type");
+                Expr2.IVal &= ExprBits - 1;
+
+            }
+
+            /* If the shift count is zero, nothing happens */
+            if (Expr2.IVal == 0) {
+
+                /* Result is already in Expr, remove the generated code */
+                RemoveCode (Mark1);
+                pop (ltype);
+
+                /* Done */
+                goto Next;
+            }
+
+            /* If the left hand side is a constant, the result is constant */
+            if (ED_IsConstAbs (Expr)) {
+
+                /* Evaluate the result */
+                switch (Tok) {
+                    case TOK_SHL: Expr->IVal <<= Expr2.IVal; break;
+                    case TOK_SHR: Expr->IVal >>= Expr2.IVal; break;
+                    default: /* Shutup gcc */                break;
+                }
+
+                /* Both operands are constant, remove the generated code */
+                RemoveCode (Mark1);
+                pop (ltype);
+
+                /* Done */
+                goto Next;
+            }
+
+            /* If we're shifting an integer or unsigned to the right, the
+             * lhs has a const address, and the shift count is larger than 8,
+             * we can load just the high byte as a char with the correct
+             * signedness, and reduce the shift count by 8. If the remaining
+             * shift count is zero, we're done.
+             */
+            if (Tok == TOK_SHR &&
+                IsTypeInt (Expr->Type) &&
+                ED_IsLVal (Expr) &&
+                (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) &&
+                Expr2.IVal >= 8) {
+
+                type* OldType;
+
+                /* Increase the address by one and decrease the shift count */
+                ++Expr->IVal;
+                Expr2.IVal -= 8;
+
+                /* Replace the type of the expression temporarily by the
+                 * corresponding char type.
+                 */
+                OldType = Expr->Type;
+                if (IsSignUnsigned (Expr->Type)) {
+                    Expr->Type = type_uchar;
+                } else {
+                    Expr->Type = type_schar;
+                }
+
+                /* Remove the generated load code */
+                RemoveCode (Mark1);
+                pop (ltype);
+
+                /* Generate again code for the load */
+                LoadExpr (CF_NONE, Expr);
+
+                /* Reset the type */
+                Expr->Type = OldType;
+
+                /* If the shift count is now zero, we're done */
+                if (Expr2.IVal == 0) {
+                    /* Be sure to mark the value as in the primary */
+                    goto Loaded;
+                }
+
+                /* Otherwise generate code to push the value */
+                Mark2 = GetCodePos ();
+                g_push (ltype, 0);
+            }
+
+        }
+
+        /* If the right hand side is a constant, remove the push of the
+         * primary register.
+         */
+        rtype = TypeOf (Expr2.Type);
+        flags = 0;
+        if (rconst) {
+            flags |= CF_CONST;
+            rtype |= CF_CONST;
+            RemoveCode (Mark2);
+            pop (ltype);
+            ltype |= CF_REG;           /* Value is in register */
+        }
+
+        /* Determine the type of the operation result. */
+        flags |= g_typeadjust (ltype, rtype);
+
+        /* Generate code */
+        switch (Tok) {
+            case TOK_SHL: g_asl (flags, Expr2.IVal); break;
+            case TOK_SHR: g_asr (flags, Expr2.IVal); break;
+            default:                                 break;
+        }
+
+Loaded:
+        /* We have a rvalue in the primary now */
+        ED_MakeRValExpr (Expr);
+
+Next:
+        /* Get the type of the result */
+               Expr->Type = IntPromotion (Expr->Type);
+    }
+}
+
+
+
diff --git a/src/cc65/shiftexpr.h b/src/cc65/shiftexpr.h
new file mode 100644 (file)
index 0000000..d5f6706
--- /dev/null
@@ -0,0 +1,74 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                shiftexpr.h                                */
+/*                                                                           */
+/*                       Parse the << and >> operators                       */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2004      Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef SHIFTEXPR_H
+#define SHIFTEXPT_H
+
+
+
+/* common */
+#include "intstack.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Forward */
+struct ExprDesc;
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+void ShiftExpr (struct ExprDesc* Expr);
+/* Parse the << and >> operators. */
+
+
+
+/* End of shiftexpr.h */
+
+#endif
+
+
+
+