]> git.sur5r.net Git - cc65/commitdiff
Work on better type casts - not yet finished
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 1 Nov 2002 15:16:16 +0000 (15:16 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 1 Nov 2002 15:16:16 +0000 (15:16 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1476 b7a2c559-68d2-44c3-8de9-860c34a00d81

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

index b43f748bf1bb5a02ecf6126f9bdd80cf3fb2275f..3142ad93b898e80f9ca69be79b924bc8a7d8b9bf 100644 (file)
@@ -31,6 +31,7 @@
 #include "scanner.h"
 #include "stdfunc.h"
 #include "symtab.h"
+#include "typecast.h"
 #include "typecmp.h"
 #include "expr.h"
 
@@ -86,9 +87,6 @@ static GenDesc GenOASGN  = { TOK_OR_ASSIGN,   GEN_NOPUSH,     g_or  };
 
 
 
-static int hie10 (ExprDesc* lval);
-/* Handle ++, --, !, unary - etc. */
-
 static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
 /* Expression parser; func is either hie0 or hie1. */
 
@@ -501,7 +499,7 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
     f = lval->Flags;
     if (k) {
                /* Dereferenced lvalue */
-       flags |= TypeOf (lval->Type);
+               flags |= TypeOf (lval->Type);
        if (lval->Test & E_FORCETEST) {
            flags |= CF_TEST;
            lval->Test &= ~E_FORCETEST;
@@ -529,10 +527,11 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
        /* Constant of some sort, load it into the primary */
        lconst (flags, lval);
     }
-    if (lval->Test & E_FORCETEST) {    /* we testing this value? */
-       /* debug... */
+    /* Are we testing this value? */
+    if (lval->Test & E_FORCETEST) {
+        /* Yes, force a test */
        flags |= TypeOf (lval->Type);
-               g_test (flags);                 /* yes, force a test */
+               g_test (flags);
                lval->Test &= ~E_FORCETEST;
     }
 }
@@ -1234,7 +1233,7 @@ static int arrayref (int k, ExprDesc* lval)
                    /* Constant numeric address. Just add it */
                    g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal);
                } else if (lflags == E_MLOCAL) {
-                   /* Base address is a local variable address */
+                   /* Base address is a local variable address */
                    if (IsTypeArray (tptr1)) {
                        g_addaddr_local (CF_INT, lval->ConstVal);
                    } else {
@@ -1291,8 +1290,8 @@ static int structref (int k, ExprDesc* lval)
     flags = lval->Flags & ~E_MCTYPE;
     if (flags == E_MCONST ||
                (k == 0 && (flags == E_MLOCAL ||
-                   (flags & E_MGLOBAL) != 0 ||
-                   lval->Flags  == E_MEOFFS))) {
+                   (flags & E_MGLOBAL) != 0 ||
+                   lval->Flags  == E_MEOFFS))) {
        lval->ConstVal += Field->V.Offs;
     } else {
        if ((flags & E_MEXPR) == 0 || k != 0) {
@@ -1490,7 +1489,7 @@ static void pre_incdec (ExprDesc* lval, void (*inc) (unsigned, unsigned long))
 
 
 
-static void post_incdec (ExprDesc *lval, int k, void (*inc) (unsigned, unsigned long))
+static void post_incdec (ExprDesclval, int k, void (*inc) (unsigned, unsigned long))
 /* Handle i-- and i++ */
 {
     unsigned flags;
@@ -1564,99 +1563,7 @@ static void unaryop (int tok, ExprDesc* lval)
 
 
 
-static int typecast (ExprDesc* lval)
-/* Handle an explicit cast */
-{
-    int k;
-    type Type[MAXTYPELEN];
-
-    /* Skip the left paren */
-    NextToken ();
-
-    /* Read the type */
-    ParseType (Type);
-
-    /* Closing paren */
-    ConsumeRParen ();
-
-    /* Read the expression we have to cast */
-    k = hie10 (lval);
-
-    /* If the expression is a function, treat it as pointer-to-function */
-    if (IsTypeFunc (lval->Type)) {
-       lval->Type = PointerTo (lval->Type);
-    }
-
-    /* Check for a constant on the right side */
-    if (k == 0 && lval->Flags == E_MCONST) {
-
-       /* A cast of a constant to something else. If the new type is an int,
-        * be sure to handle the size extension correctly. If the new type is
-        * not an int, the cast is implementation specific anyway, so leave
-        * the value alone.
-        */
-       if (IsClassInt (Type)) {
-
-           /* Get the current and new size of the value */
-           unsigned OldBits = CheckedSizeOf (lval->Type) * 8;
-           unsigned NewBits = CheckedSizeOf (Type)       * 8;
-
-           /* Check if the new datatype will have a smaller range */
-                   if (NewBits <= OldBits) {
-
-               /* Cut the value to the new size */
-               lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
-
-               /* If the new type is signed, sign extend the value */
-               if (!IsSignUnsigned (Type)) {
-                   lval->ConstVal |= ((~0L) << NewBits);
-               }
-
-           } else {
-
-               /* Sign extend the value if needed */
-               if (!IsSignUnsigned (lval->Type) && !IsSignUnsigned (Type)) {
-                   if (lval->ConstVal & (0x01UL << (OldBits-1))) {
-                       lval->ConstVal |= ((~0L) << OldBits);
-                   }
-               }
-           }
-       }
-
-    } else {
-
-       /* Not a constant. Be sure to ignore casts to void */
-       if (!IsTypeVoid (Type)) {
-
-           /* If the size does not change, leave the value alone. Otherwise,
-            * we have to load the value into the primary and generate code to
-            * cast the value in the primary register.
-            */
-           if (SizeOf (Type) != SizeOf (lval->Type)) {
-
-               /* Load the value into the primary */
-               exprhs (CF_NONE, k, lval);
-
-                       /* Emit typecast code */
-               g_typecast (TypeOf (Type), TypeOf (lval->Type));
-
-               /* Value is now in primary */
-               lval->Flags = E_MEXPR;
-                       k = 0;
-           }
-       }
-    }
-
-    /* In any case, use the new type */
-    lval->Type = TypeDup (Type);
-
-    /* Done */
-    return k;
-}
-
-
-
-static int hie10 (ExprDesc* lval)
+int hie10 (ExprDesc* lval)
 /* Handle ++, --, !, unary - etc. */
 {
     int k;
@@ -1747,7 +1654,7 @@ static int hie10 (ExprDesc* lval)
        default:
                    if (istypeexpr ()) {
                /* A cast */
-               return typecast (lval);
+               return TypeCast (lval);
            }
     }
 
index fabd91b40e5c2754504a99edf3d3f37b4f3f6049..7933a7f4d697f2999168ec09d66d26c7a904bec7 100644 (file)
@@ -107,6 +107,9 @@ void boolexpr (ExprDesc* lval);
 void test (unsigned label, int cond);
 /* Generate code to perform test and jump if false. */
 
+int hie10 (ExprDesc* lval);
+/* Handle ++, --, !, unary - etc. */
+
 int hie1 (ExprDesc* lval);
 /* Parse first level of expression hierarchy. */
 
index 7446bb8d0fc1c9a9817f02753ec16fc2d266fb1c..62a9e36cf44146cc92cdbca625208134e0ee61f1 100644 (file)
@@ -81,6 +81,7 @@ OBJS =        anonname.o      \
        symentry.o      \
        symtab.o        \
        textseg.o       \
+        typecast.o      \
        typecmp.o       \
        util.o
 
index b55980c18e07237a992dc20321f8fd4f69db8836..af17be50ae29f50a4d08eb1c0dd0781fa272f761 100644 (file)
@@ -126,6 +126,7 @@ OBJS =      anonname.obj    \
        symentry.obj    \
        symtab.obj      \
        textseg.obj     \
+        typecast.obj    \
        typecmp.obj     \
        util.obj
 
@@ -209,6 +210,7 @@ FILE swstmt.obj
 FILE symentry.obj
 FILE symtab.obj
 FILE textseg.obj
+FILE typecast.obj
 FILE typecmp.obj
 FILE util.obj
 LIBRARY ..\common\common.lib
diff --git a/src/cc65/typecast.c b/src/cc65/typecast.c
new file mode 100644 (file)
index 0000000..ec1111a
--- /dev/null
@@ -0,0 +1,212 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typecast.c                                 */
+/*                                                                           */
+/*                             Handle type casts                             */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* 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 "codegen.h"
+#include "datatype.h"
+#include "declare.h"
+#include "error.h"
+#include "expr.h"
+#include "scanner.h"
+#include "typecast.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+int TypeCast (ExprDesc* lval)
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+{
+    int      k;
+    type*    OldType;
+    type     NewType[MAXTYPELEN];
+    unsigned OldSize;
+    unsigned NewSize;
+
+    /* Skip the left paren */
+    NextToken ();
+
+    /* Read the type */
+    ParseType (NewType);
+
+    /* Closing paren */
+    ConsumeRParen ();
+
+    /* Read the expression we have to cast */
+    k = hie10 (lval);
+
+    /* If the expression is a function, treat it as pointer-to-function */
+    if (IsTypeFunc (lval->Type)) {
+       lval->Type = PointerTo (lval->Type);
+    }
+
+    /* Remember the old type and use the new one */
+    OldType = lval->Type;
+    lval->Type = TypeDup (NewType);
+
+    /* If we're casting to void, we're done. Note: This does also cover a cast
+     * void -> void.
+     */
+    if (IsTypeVoid (NewType)) {
+        return 0;       /* Never an lvalue */
+    }
+
+    /* Don't allow casts from void to something else. The new type is already
+     * set which should avoid more errors, but code will not get generated
+     * because of the error.
+     */
+    if (IsTypeVoid (OldType)) {
+        Error ("Cannot cast from `void' to something else");
+        return k;
+    }
+
+    /* Get the sizes of the types. Since we've excluded void types, checking
+     * for known sizes makes sense here.
+     */
+    OldSize = CheckedSizeOf (OldType);
+    NewSize = CheckedSizeOf (NewType);
+
+    /* Is this a cast of something into an integer? */
+    if (IsClassInt (NewType)) {
+
+        /* lvalue? */
+        if (k != 0) {
+
+            /* We have an lvalue. If the new size is smaller than the new one,
+             * we don't need to do anything. The compiler will generate code
+             * to load only the portion of the value that is actually needed.
+             * This works only on a little endian architecture, but that's
+             * what we support.
+             * If both sizes are equal, do also leave the value alone.
+             * If the new size is larger, we must convert the value.
+             */
+            if (NewSize > OldSize) {
+                /* Load the value into the primary */
+                exprhs (CF_NONE, k, lval);
+
+                /* Emit typecast code */
+                g_typecast (TypeOf (OldType), TypeOf (NewType));
+
+                /* Value is now in primary */
+                lval->Flags = E_MEXPR;
+                k = 0;
+            }
+
+        } else {
+
+            /* We have an rvalue. Check for a constant. */
+            if (lval->Flags == E_MCONST) {
+
+                /* A cast of a constant to an integer. Be sure to handle sign
+                 * extension correctly.
+                 */
+
+                /* Get the current and new size of the value */
+                unsigned OldBits = OldSize * 8;
+                unsigned NewBits = NewSize * 8;
+
+                /* Check if the new datatype will have a smaller range */
+                if (NewBits <= OldBits) {
+
+                    /* Cut the value to the new size */
+                    lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
+
+                    /* If the new type is signed, sign extend the value */
+                    if (!IsSignUnsigned (NewType)) {
+                        lval->ConstVal |= ((~0L) << NewBits);
+                    }
+
+                } else {
+
+                    /* Sign extend the value if needed */
+                    if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
+                        if (lval->ConstVal & (0x01UL << (OldBits-1))) {
+                            lval->ConstVal |= ((~0L) << OldBits);
+                        }
+                    }
+                }
+
+            } else {
+
+                /* The value is not a constant. If the sizes of the types are
+                 * not equal, add conversion code. Be sure to convert chars
+                 * correctly.
+                 */
+                if (OldSize != NewSize) {
+
+                    /* Load the value into the primary */
+                    exprhs (CF_NONE, k, lval);
+
+                    /* Emit typecast code. ### CHARS */
+                    g_typecast (TypeOf (OldType), TypeOf (NewType));
+
+                    /* Value is now in primary */
+                    lval->Flags = E_MEXPR;
+                    k = 0;
+                }
+            }
+        }
+
+    } else {
+
+        /* All other stuff is handled equally */
+        if (NewSize != OldSize) {
+            /* Load the value into the primary */
+            exprhs (CF_NONE, k, lval);
+
+            /* Emit typecast code */
+            g_typecast (TypeOf (OldType), TypeOf (NewType));
+
+            /* Value is now in primary */
+            lval->Flags = E_MEXPR;
+            k = 0;
+        }
+    }
+
+    /* Done */
+    return k;
+}
+
+
+
+
+
+
diff --git a/src/cc65/typecast.h b/src/cc65/typecast.h
new file mode 100644 (file)
index 0000000..b6086d6
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typecast.h                                 */
+/*                                                                           */
+/*                             Handle type casts                             */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002      Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* 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 TYPECAST_H
+#define TYPECAST_H
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+int TypeCast (ExprDesc* lval);
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+
+
+
+/* End of typecast.h */
+#endif
+
+
+