]> git.sur5r.net Git - cc65/commitdiff
Added license information preproc.h
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 29 Jun 2004 20:26:27 +0000 (20:26 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 29 Jun 2004 20:26:27 +0000 (20:26 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3135 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/expr.c
src/cc65/expr.h
src/cc65/exprdesc.c
src/cc65/exprdesc.h
src/cc65/preproc.c
src/cc65/preproc.h
src/cc65/typeconv.c

index c35bb241b258f731a8f2206b5fcbdc03f3c234a2..93746b4df1988d74ca1278f48fc7891a56388a32 100644 (file)
@@ -57,6 +57,7 @@
 
 
 /* Predefined type strings */
+type type_schar[]       = { T_SCHAR,           T_END };
 type type_uchar[]       = { T_UCHAR,   T_END };
 type type_int[]         = { T_INT,     T_END };
 type type_uint[]        = { T_UINT,    T_END };
@@ -777,3 +778,23 @@ type* GetElementType (type* T)
 
 
 
+type* IntPromotion (type* T)
+/* Apply the integer promotions to T and return the result. The returned type
+ * string may be T if there is no need to change it.
+ */
+{
+    /* We must have an int to apply int promotions */
+    PRECONDITION (IsClassInt (T));
+
+    /* An integer can represent all values from either signed or unsigned char,
+     * so convert chars to int and leave all other types alone.
+     */
+    if (IsTypeChar (T)) {
+        return type_int;
+    } else {
+        return T;
+    }
+}
+
+
+
index 180654133f1c98c91ebef5799b7ed9fce6b7fe90..cf78490428c15a5c4f451cadf0dfa810c85be95c 100644 (file)
@@ -161,6 +161,7 @@ typedef unsigned short type;
 #define SIZEOF_PTR      2
 
 /* Predefined type strings */
+extern type type_schar[];
 extern type type_uchar[];
 extern type type_int[];
 extern type type_uint[];
@@ -490,6 +491,11 @@ long GetElementCount (const type* T);
 type* GetElementType (type* T);
 /* Return the element type of the given array type. */
 
+type* IntPromotion (type* T);
+/* Apply the integer promotions to T and return the result. The returned type
+ * string may be T if there is no need to change it.
+ */
+
 
 
 /* End of datatype.h */
index 6cff40326a7c48ecfbfa96e78bc82f5da908aa5b..6cd41138b33bf2021beca923d0d09761730a1526 100644 (file)
@@ -68,17 +68,6 @@ static GenDesc GenOASGN  = { TOK_OR_ASSIGN,  GEN_NOPUSH,     g_or  };
 
 
 
-/*****************************************************************************/
-/*                            Function forwards                             */
-/*****************************************************************************/
-
-
-
-void hie0 (ExprDesc *lval);
-/* Parse comma operator. */
-
-
-
 /*****************************************************************************/
 /*                            Helper functions                              */
 /*****************************************************************************/
@@ -97,7 +86,7 @@ static unsigned GlobalModeFlags (unsigned Flags)
     }
 }
 
-
+             
 
 void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr)
 /* Call an expression function with checks. */
@@ -2277,7 +2266,7 @@ static void parsesub (ExprDesc* Expr)
 
 
 
-static void hie8 (ExprDesc* Expr)
+void hie8 (ExprDesc* Expr)
 /* Process + and - binary operators. */
 {
     hie9 (Expr);
@@ -2293,16 +2282,191 @@ static void hie8 (ExprDesc* Expr)
 
 
 static void hie7 (ExprDesc* Expr)
-/* Parse << and >>. */
+/* Parse the << and >> operators. */
 {
-    static const GenDesc hie7_ops [] = {
-        { TOK_SHL,     GEN_NOPUSH,     g_asl   },
-        { TOK_SHR,     GEN_NOPUSH,     g_asr   },
-        { TOK_INVALID,  0,              0       }
-    };
-    int UsedGen;
+    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);
+       }
 
-    hie_internal (hie7_ops, Expr, hie8, &UsedGen);
+       /* 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);
+    }
 }
 
 
index 9f5668977b1938459e90865a2daa61dcd2268a2a..e166dd5ee6de31605e55acd4be2b6d5b3b1d11d1 100644 (file)
@@ -39,9 +39,6 @@ void Store (ExprDesc* Expr, const type* StoreType);
  * is NULL, use lval->Type instead.
  */
 
-void hie0 (ExprDesc* Expr);
-/* Parse comma operator. */
-
 int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr);
 /* Will evaluate an expression via the given function. If the result is a
  * constant, 0 is returned and the value is put in the lval struct. If the
@@ -76,9 +73,15 @@ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr);
 void hie10 (ExprDesc* lval);
 /* Handle ++, --, !, unary - etc. */
 
+void hie8 (ExprDesc* Expr);
+/* Process + and - binary operators. */
+
 void hie1 (ExprDesc* lval);
 /* Parse first level of expression hierarchy. */
 
+void hie0 (ExprDesc* Expr);
+/* Parse comma operator. */
+
 void DefineData (ExprDesc* lval);
 /* Output a data definition for the given expression */
 
index 9b9a0a6fb4a90c69133785252e0b18f9e062f8a9..4de2a6adfe428d4752c79dd85b7f5aea8a53535d 100644 (file)
@@ -192,7 +192,7 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
     Expr->Name  = 0;
     Expr->IVal  = 0;    /* No offset */
-    Expr->FVal  = 0.0; 
+    Expr->FVal  = 0.0;
     return Expr;
 }
 
@@ -209,16 +209,6 @@ int ED_IsConst (const ExprDesc* Expr)
 
 
 
-int ED_IsConstAbs (const ExprDesc* Expr)
-/* Return true if the expression denotes a constant absolute value. This can be
- * a numeric constant, cast to any type.
- */
-{
-    return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
-}
-
-
-
 int ED_IsConstAbsInt (const ExprDesc* Expr)
 /* Return true if the expression is a constant (numeric) integer. */
 {
index 97f87b1627dec5000fd673634c5fa93360efb063..7b945666c7b7c10ba20e46f096bce36b2a94de82 100644 (file)
@@ -307,10 +307,18 @@ int ED_IsConst (const ExprDesc* Expr);
  * similar.
  */
 
-int ED_IsConstAbs (const ExprDesc* Expr);
+#if defined(HAVE_INLINE)
+INLINE int ED_IsConstAbs (const ExprDesc* Expr)
 /* Return true if the expression denotes a constant absolute value. This can be
  * a numeric constant, cast to any type.
  */
+{
+    return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
+}
+#else
+#  define ED_IsConstAbs(E)      \
+        (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL))
+#endif
 
 int ED_IsConstAbsInt (const ExprDesc* Expr);
 /* Return true if the expression is a constant (numeric) integer. */
index e22727d65f335955f4fd6de02901d9a6fd8b8fa8..28232208560862595182cb723a81e25db89defb0 100644 (file)
@@ -1,6 +1,9 @@
-
-/* C pre-processor functions */
-
+/* 
+ * C pre-processor functions.
+ * Portions of this code are copyright (C) 1989 John R. Dunning.  
+ * See copyleft.jrd for license information.
+ */
+   
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
index b6fc559cfca89a628099dd08297327a3851a4b8d..286d309d1ba138d0a505eadb4dfe0e0c3ed32ddd 100644 (file)
@@ -1,8 +1,35 @@
-/*
- * preproc.h
- *
- * Ullrich von Bassewitz, 07.06.1998
- */
+/*****************************************************************************/
+/*                                                                           */
+/*                                 preproc.h                                 */
+/*                                                                           */
+/*                              C preprocessor                               */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 1998-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.                                                          */
+/*                                                                           */
+/*****************************************************************************/
 
 
 
@@ -17,7 +44,7 @@
 
 
 
-/* Set when the pp calls expr() recursively */
+/* Set when the preprocessor calls ConstExpr() recursively */
 extern unsigned char Preprocessing;
 
 
index 3b30461c7ffcb3357176f782c84b8949645701df..cf3c9a3ef4bbb1b8f7a21bc6bd5c47384f8c56f8 100644 (file)
@@ -195,6 +195,12 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
                Error ("Illegal type");
     }
 
+    /* If both types are equal, no conversion is needed */
+    if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) {
+        /* We're already done */
+        return;
+    }
+
     /* Check for conversion problems */
     if (IsClassInt (NewType)) {
 
@@ -202,10 +208,16 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
                if (IsClassPtr (Expr->Type)) {
            /* Pointer -> int conversion */
            Warning ("Converting pointer to integer without a cast");
-               } else if (!IsClassInt (Expr->Type)) {
+               } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
            Error ("Incompatible types");
                }
 
+    } else if (IsClassFloat (NewType)) {
+
+        if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) {
+            Error ("Incompatible types");
+        }
+
     } else if (IsClassPtr (NewType)) {
 
         /* Handle conversions to pointer type */
@@ -213,40 +225,40 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
            /* Pointer to pointer assignment is valid, if:
             *   - both point to the same types, or
             *   - the rhs pointer is a void pointer, or
-            *   - the lhs pointer is a void pointer.
+            *   - the lhs pointer is a void pointer.
             */
-           if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
-               /* Compare the types */
-               switch (TypeCmp (NewType, Expr->Type)) {
-
-                   case TC_INCOMPATIBLE:
-                       Error ("Incompatible pointer types");
-                       break;
-
-                   case TC_QUAL_DIFF:
-                       Error ("Pointer types differ in type qualifiers");
-                       break;
-
-                   default:
-                       /* Ok */
-                       break;
-               }
-           }
+           if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
+               /* Compare the types */
+               switch (TypeCmp (NewType, Expr->Type)) {
+
+                   case TC_INCOMPATIBLE:
+                       Error ("Incompatible pointer types");
+                       break;
+
+                   case TC_QUAL_DIFF:
+                       Error ("Pointer types differ in type qualifiers");
+                       break;
+
+                   default:
+                       /* Ok */
+                       break;
+               }
+           }
        } else if (IsClassInt (Expr->Type)) {
            /* Int to pointer assignment is valid only for constant zero */
            if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) {
                Warning ("Converting integer to pointer without a cast");
            }
-       } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
-           /* Assignment of function to function pointer is allowed, provided
-            * that both functions have the same parameter list.
-            */
-           if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
-               Error ("Incompatible types");
-           }
+       } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
+           /* Assignment of function to function pointer is allowed, provided
+            * that both functions have the same parameter list.
+            */
+           if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
+               Error ("Incompatible types");
+           }
        } else {
-           Error ("Incompatible types");
-       }
+           Error ("Incompatible types");
+       }
 
     } else {