]> git.sur5r.net Git - cc65/blobdiff - src/ca65/studyexpr.c
Finished implemenation of commands to delete macros. Added the new commands to
[cc65] / src / ca65 / studyexpr.c
index 56821b90cd3fd10a47cdd68325f7f632c0141855..42a8dbbd6a748b513b53791aad8cc49a6ebc357c 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003      Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
+/* (C) 2003-2007 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -226,7 +226,7 @@ static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym)
     SymRef = ED->SymRef + ED->SymCount++;
 
     /* Initialize the new struct and return it */
-    SymRef->Count = 1;
+    SymRef->Count = 0;
     SymRef->Ref   = Sym;
     return SymRef;
 }
@@ -335,6 +335,20 @@ static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New)
 
 
 
+static void ED_NegRefs (ExprDesc* D)
+/* Negate the references in ED */
+{
+    unsigned I;
+    for (I = 0; I < D->SymCount; ++I) {
+        D->SymRef[I].Count = -D->SymRef[I].Count;
+    }
+    for (I = 0; I < D->SecCount; ++I) {
+        D->SecRef[I].Count = -D->SecRef[I].Count;
+    }
+}
+
+
+
 static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
 /* Calculate ED = ED + Right, update address size in ED */
 {
@@ -345,6 +359,19 @@ static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
 
 
 
+static void ED_Sub (ExprDesc* ED, const ExprDesc* Right)
+/* Calculate ED = ED - Right, update address size in ED */
+{
+    ExprDesc D = *Right;        /* Temporary */
+    ED_NegRefs (&D);
+
+    ED->Val -= Right->Val;
+    ED_MergeRefs (ED, &D);      /* Merge negatives */
+    ED_MergeAddrSize (ED, Right);
+}
+
+
+
 static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
 /* Calculate ED = ED * Right, update address size in ED */
 {
@@ -365,15 +392,8 @@ static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
 static void ED_Neg (ExprDesc* D)
 /* Negate an expression */
 {
-    unsigned I;
-
     D->Val = -D->Val;
-    for (I = 0; I < D->SymCount; ++I) {
-        D->SymRef[I].Count = -D->SymRef[I].Count;
-    }
-    for (I = 0; I < D->SecCount; ++I) {
-        D->SecRef[I].Count = -D->SecRef[I].Count;
-    }
+    ED_NegRefs (D);
 }
 
 
@@ -406,6 +426,22 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D);
 
 
 
+static unsigned char GetConstAddrSize (long Val)
+/* Get the address size of a constant */
+{
+    if ((Val & ~0xFFL) == 0) {
+        return ADDR_SIZE_ZP;
+    } else if ((Val & ~0xFFFFL) == 0) {
+        return ADDR_SIZE_ABS;
+    } else if ((Val & ~0xFFFFFFL) == 0) {
+        return ADDR_SIZE_FAR;
+    } else {
+        return ADDR_SIZE_LONG;
+    }
+}
+
+
+
 static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
 /* Study a binary expression subtree. This is a helper function for StudyExpr
  * used for operations that succeed when both operands are known and constant.
@@ -450,9 +486,9 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
 static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
 /* Study a literal expression node */
 {
-
     /* This one is easy */
-    D->Val = Expr->V.Val;
+    D->Val      = Expr->V.IVal;
+    D->AddrSize = GetConstAddrSize (D->Val);
 }
 
 
@@ -474,9 +510,9 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
             if (Verbosity > 0) {
                 DumpExpr (Expr, SymResolve);
             }
-            PError (GetSymPos (Sym),
-                    "Circular reference in definition of symbol `%s'",
-                    GetSymName (Sym));
+            LIError (&Sym->LineInfos,
+                     "Circular reference in definition of symbol `%m%p'",
+                     GetSymName (Sym));
             ED_Invalidate (D);
         } else {
 
@@ -545,7 +581,7 @@ static void StudySection (ExprNode* Expr, ExprDesc* D)
 /* Study a section expression node */
 {
     /* Get the section reference */
-    ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SegNum);
+    ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum);
 
     /* Update the data and the address size */
     ++SecRef->Count;
@@ -562,7 +598,7 @@ static void StudyULabel (ExprNode* Expr, ExprDesc* D)
      */
     if (ULabCanResolve ()) {
         /* We can resolve the label */
-        StudyExprInternal (ULabResolve (Expr->V.Val), D);
+        StudyExprInternal (ULabResolve (Expr->V.IVal), D);
     } else {
         ED_Invalidate (D);
     }
@@ -583,7 +619,7 @@ static void StudyPlus (ExprNode* Expr, ExprDesc* D)
     StudyExprInternal (Expr->Right, &Right);
 
     /* Check if we can handle the operation */
-    if (ED_IsValid (D) || ED_IsValid (&Right)) {
+    if (ED_IsValid (D) && ED_IsValid (&Right)) {
 
         /* Add both */
         ED_Add (D, &Right);
@@ -618,11 +654,10 @@ static void StudyMinus (ExprNode* Expr, ExprDesc* D)
     StudyExprInternal (Expr->Right, &Right);
 
     /* Check if we can handle the operation */
-    if (ED_IsValid (D) || ED_IsValid (&Right)) {
+    if (ED_IsValid (D) && ED_IsValid (&Right)) {
 
         /* Subtract both */
-        ED_Neg (&Right);
-        ED_Add (D, &Right);
+        ED_Sub (D, &Right);
 
     } else {
 
@@ -967,6 +1002,34 @@ static void StudyBoolXor (ExprNode* Expr, ExprDesc* D)
 
 
 
+static void StudyMax (ExprNode* Expr, ExprDesc* D)
+/* Study an MAX binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val > D->Right)? D->Val : D->Right;
+    }
+}
+
+
+
+static void StudyMin (ExprNode* Expr, ExprDesc* D)
+/* Study an MIN binary expression node */
+{
+    /* Use helper function */
+    StudyBinaryExpr (Expr, D);
+
+    /* If the result is valid, apply the operation */
+    if (ED_IsValid (D)) {
+        D->Val = (D->Val < D->Right)? D->Val : D->Right;
+    }
+}
+
+
+
 static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D)
 /* Study an EXPR_UNARY_MINUS expression node */
 {
@@ -1244,6 +1307,14 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
             StudyBoolXor (Expr, D);
             break;
 
+        case EXPR_MAX:
+            StudyMax (Expr, D);
+            break;
+
+        case EXPR_MIN:
+            StudyMin (Expr, D);
+            break;
+
         case EXPR_UNARY_MINUS:
             StudyUnaryMinus (Expr, D);
             break;
@@ -1295,13 +1366,13 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
 void StudyExpr (ExprNode* Expr, ExprDesc* D)
 /* Study an expression tree and place the contents into D */
 {
-    unsigned I;
+    unsigned I, J;
 
     /* Call the internal function */
     StudyExprInternal (Expr, D);
 
     /* Remove symbol references with count zero */
-    I = 0;
+    I = J = 0;
     while (I < D->SymCount) {
         if (D->SymRef[I].Count == 0) {
             /* Delete the entry */
@@ -1328,32 +1399,64 @@ void StudyExpr (ExprNode* Expr, ExprDesc* D)
         }
     }
 
-    /* If we don't have an address size, assign one of the expression is a
+    /* If we don't have an address size, assign one if the expression is a
      * constant.
      */
-    if (D->AddrSize == ADDR_SIZE_DEFAULT) {
-        if (ED_IsConst (D)) {
-            if ((D->Val & ~0xFFL) == 0) {
-                D->AddrSize = ADDR_SIZE_ZP;
-            } else if ((D->Val & ~0xFFFFL) == 0) {
-                D->AddrSize = ADDR_SIZE_ABS;
-            } else if ((D->Val & 0xFFFFFFL) == 0) {
-                D->AddrSize = ADDR_SIZE_FAR;
-            } else {
-                D->AddrSize = ADDR_SIZE_LONG;
+    if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) {
+        D->AddrSize = GetConstAddrSize (D->Val);
+    }
+
+    /* If the expression is valid, throw away the address size and recalculate
+     * it using the data we have. This is more exact than the on-the-fly
+     * calculation done when evaluating the tree, because symbols may have
+     * been removed from the expression, and the final numeric value is now
+     * known.
+     */
+    if (ED_IsValid (D)) {
+        unsigned char AddrSize;
+
+        /* If there are symbols or sections, use the largest one. If the
+         * expression resolves to a const, use the address size of the value.
+         */
+        if (D->SymCount > 0 || D->SecCount > 0) {
+
+            D->AddrSize = ADDR_SIZE_DEFAULT;
+
+            for (I = 0; I < D->SymCount; ++I) {
+                const SymEntry* Sym = D->SymRef[I].Ref;
+                AddrSize = GetSymAddrSize (Sym);
+                if (AddrSize > D->AddrSize) {
+                    D->AddrSize = AddrSize;
+                }
+            }
+
+            for (I = 0; I < D->SecCount; ++I) {
+                unsigned SegNum = D->SecRef[0].Ref;
+                AddrSize = GetSegAddrSize (SegNum);
+                if (AddrSize > D->AddrSize) {
+                    D->AddrSize = AddrSize;
+                }
+            }
+
+        } else {
+            AddrSize = GetConstAddrSize (D->Val);
+            if (AddrSize > D->AddrSize) {
+                D->AddrSize = AddrSize;
             }
         }
     }
 
 #if 0
+    /* Debug code */
     printf ("StudyExpr: "); DumpExpr (Expr, SymResolve);
+    printf ("Value: %08lX\n", D->Val);
     if (!ED_IsValid (D)) {
         printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize));
     } else {
         printf ("Valid:   %s\n", AddrSizeToStr (D->AddrSize));
-        printf ("%u symbols:\n", D->SymCount);
-        printf ("%u sections:\n", D->SecCount);
     }
+    printf ("%u symbols:\n", D->SymCount);
+    printf ("%u sections:\n", D->SecCount);
 #endif
 }