]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Fixed more E_MCONST issues
[cc65] / src / cc65 / expr.c
index f517933f4f11afd1aeb1c29e3e04c7e6ecbfa18e..276215f7418617bcd7a9695cbf99f5d19121d30f 100644 (file)
@@ -226,7 +226,7 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
             * as const.
             */
            unsigned flags = TypeOf (rhst);
-                   if (rhs->e_flags & E_MCONST) {
+                   if (rhs->e_flags == E_MCONST) {
                flags |= CF_CONST;
            }
            return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
@@ -257,7 +257,7 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
            }
        } else if (IsClassInt (rhst)) {
            /* Int to pointer assignment is valid only for constant zero */
-           if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
+           if (rhs->e_flags != E_MCONST || rhs->e_const != 0) {
                Warning ("Converting integer to pointer without a cast");
            }
        } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
@@ -309,7 +309,7 @@ void DefineData (struct expent* lval)
 
                case E_TLIT:
            /* a literal of some kind */
-                   g_defdata (CF_STATIC, LiteralLabel, lval->e_const);
+                   g_defdata (CF_STATIC, LiteralPoolLabel, lval->e_const);
                    break;
 
                default:
@@ -352,7 +352,7 @@ static void lconst (unsigned flags, struct expent* lval)
 
                case E_TLIT:
            /* Literal string */
-           g_getimmed (CF_STATIC, LiteralLabel, lval->e_const);
+           g_getimmed (CF_STATIC, LiteralPoolLabel, lval->e_const);
                    break;
 
                default:
@@ -431,13 +431,12 @@ static int istypeexpr (void)
 {
     SymEntry* Entry;
 
-    return curtok == TOK_LPAREN && (
-                   (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
-           (nxttok == TOK_CONST)                               ||
-                   (nxttok  == TOK_IDENT                               &&
-           (Entry = FindSym (NextTok.Ident)) != 0              &&
-           IsTypeDef (Entry))
-           );
+    return CurTok.Tok == TOK_LPAREN && (
+                  (NextTok.Tok >= TOK_FIRSTTYPE && NextTok.Tok <= TOK_LASTTYPE) ||
+          (NextTok.Tok == TOK_CONST)                                    ||
+                  (NextTok.Tok  == TOK_IDENT                                    &&
+          (Entry = FindSym (NextTok.Ident)) != 0                        &&
+          IsTypeDef (Entry)));
 }
 
 
@@ -502,7 +501,6 @@ void exprhs (unsigned flags, int k, struct expent *lval)
     }
     if (lval->e_test & E_FORCETEST) {  /* we testing this value? */
        /* debug... */
-       AddCodeHint ("forcetest");
        flags |= TypeOf (lval->e_tptr);
                g_test (flags);                 /* yes, force a test */
                lval->e_test &= ~E_FORCETEST;
@@ -564,14 +562,11 @@ static unsigned FunctionParamList (FuncDesc* Func)
     }
 
     /* Parse the actual parameter list */
-    while (curtok != TOK_RPAREN) {
+    while (CurTok.Tok != TOK_RPAREN) {
 
        unsigned CFlags;
        unsigned Flags;
 
-       /* Add a hint for the optimizer */
-       AddCodeHint ("param:start");
-
        /* Count arguments */
        ++ParamCount;
 
@@ -644,26 +639,23 @@ static unsigned FunctionParamList (FuncDesc* Func)
        } else {
            unsigned ArgSize = sizeofarg (Flags);
            if (FrameSize > 0) {
-               /* We have the space already allocated, store in the frame */
-               CHECK (FrameSize >= ArgSize);
-               FrameSize -= ArgSize;
-               FrameOffs -= ArgSize;
-               /* Store */
-               g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
+               /* We have the space already allocated, store in the frame */
+               CHECK (FrameSize >= ArgSize);
+               FrameSize -= ArgSize;
+               FrameOffs -= ArgSize;
+               /* Store */
+               g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
            } else {
                /* Push the argument */
-               g_push (Flags, lval.e_const);
+               g_push (Flags, lval.e_const);
            }
 
            /* Calculate total parameter size */
            ParamSize += ArgSize;
        }
 
-       /* Add an optimizer hint */
-       AddCodeHint ("param:end");
-
        /* Check for end of argument list */
-       if (curtok != TOK_COMMA) {
+       if (CurTok.Tok != TOK_COMMA) {
            break;
        }
        NextToken ();
@@ -674,8 +666,15 @@ static unsigned FunctionParamList (FuncDesc* Func)
        Error ("Too few arguments in function call");
     }
 
-    /* Return the size of all parameters pushed onto the stack */
-    return ParamSize;
+    /* The function returns the size of all parameters pushed onto the stack.
+     * However, if there are parameters missing (which is an error and was
+     * flagged by the compiler) AND a stack frame was preallocated above,
+     * we would loose track of the stackpointer and generate an internal error
+     * later. So we correct the value by the parameters that should have been
+     * pushed to avoid an internal compiler error. Since an error was
+     * generated before, no code will be output anyway.
+     */
+    return ParamSize + FrameSize;
 }
 
 
@@ -745,18 +744,35 @@ void doasm (void)
     ConsumeLParen ();
 
     /* String literal */
-    if (curtok != TOK_SCONST) {
+    if (CurTok.Tok != TOK_SCONST) {
        Error ("String literal expected");
     } else {
-       /* Write the string directly into the output, followed by a newline */
-               AddCodeLine (GetLiteral (curval));
+
+       /* The string literal may consist of more than one line of assembler
+        * code. Separate the single lines and output the code.
+        */
+       const char* S = GetLiteral (CurTok.IVal);
+       while (*S) {
+
+           /* Allow lines up to 256 bytes */
+           const char* E = strchr (S, '\n');
+           if (E) {
+               /* Found a newline */
+               g_asmcode (S, E-S);
+               S = E+1;
+           } else {
+               int Len = strlen (S);
+               g_asmcode (S, Len);
+               S += Len;
+           }
+       }
 
        /* Reset the string pointer, effectivly clearing the string from the
         * string table. Since we're working with one token lookahead, this
         * will fail if the next token is also a string token, but that's a
         * syntax error anyway, because we expect a right paren.
         */
-       ResetLiteralOffs (curval);
+       ResetLiteralPoolOffs (CurTok.IVal);
     }
 
     /* Skip the string token */
@@ -777,10 +793,10 @@ static int primary (struct expent* lval)
     lval->e_test = 0;
 
     /* Character and integer constants. */
-    if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
+    if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
        lval->e_flags = E_MCONST | E_TCONST;
-       lval->e_tptr  = curtype;
-       lval->e_const = curval;
+       lval->e_tptr  = CurTok.Type;
+       lval->e_const = CurTok.IVal;
        NextToken ();
        return 0;
     }
@@ -788,7 +804,7 @@ static int primary (struct expent* lval)
     /* Process parenthesized subexpression by calling the whole parser
      * recursively.
      */
-    if (curtok == TOK_LPAREN) {
+    if (CurTok.Tok == TOK_LPAREN) {
        NextToken ();
        memset (lval, 0, sizeof (*lval));       /* Remove any attributes */
        k = hie0 (lval);
@@ -808,7 +824,7 @@ static int primary (struct expent* lval)
     }
 
     /* Identifier? */
-    if (curtok == TOK_IDENT) {
+    if (CurTok.Tok == TOK_IDENT) {
 
        SymEntry* Sym;
        ident Ident;
@@ -898,7 +914,7 @@ static int primary (struct expent* lval)
        NextToken ();
 
        /* IDENT is either an auto-declared function or an undefined variable. */
-       if (curtok == TOK_LPAREN) {
+       if (CurTok.Tok == TOK_LPAREN) {
            /* Declare a function returning int. For that purpose, prepare a
             * function signature for a function having an empty param list
             * and returning int.
@@ -925,16 +941,16 @@ static int primary (struct expent* lval)
     }
 
     /* String literal? */
-    if (curtok == TOK_SCONST) {
+    if (CurTok.Tok == TOK_SCONST) {
        lval->e_flags = E_MCONST | E_TLIT;
-               lval->e_const = curval;
-       lval->e_tptr  = GetCharArrayType (strlen (GetLiteral (curval)));
+               lval->e_const = CurTok.IVal;
+       lval->e_tptr  = GetCharArrayType (strlen (GetLiteral (CurTok.IVal)));
        NextToken ();
        return 0;
     }
 
     /* ASM statement? */
-    if (curtok == TOK_ASM) {
+    if (CurTok.Tok == TOK_ASM) {
        doasm ();
        lval->e_tptr  = type_void;
        lval->e_flags = E_MEXPR;
@@ -943,8 +959,8 @@ static int primary (struct expent* lval)
     }
 
     /* __AX__ and __EAX__ pseudo values? */
-    if (curtok == TOK_AX || curtok == TOK_EAX) {
-               lval->e_tptr  = (curtok == TOK_AX)? type_uint : type_ulong;
+    if (CurTok.Tok == TOK_AX || CurTok.Tok == TOK_EAX) {
+               lval->e_tptr  = (CurTok.Tok == TOK_AX)? type_uint : type_ulong;
        lval->e_flags = E_MREG;
        lval->e_test &= ~E_CC;
        lval->e_const = 0;
@@ -1203,7 +1219,7 @@ static int structref (int k, struct expent* lval)
 
     /* Skip the token and check for an identifier */
     NextToken ();
-    if (curtok != TOK_IDENT) {
+    if (CurTok.Tok != TOK_IDENT) {
        Error ("Identifier expected");
        lval->e_tptr = type_int;
        return 0;
@@ -1247,19 +1263,19 @@ static int hie11 (struct expent *lval)
 
 
     k = primary (lval);
-    if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
+    if (CurTok.Tok < TOK_LBRACK || CurTok.Tok > TOK_PTR_REF) {
        /* Not for us */
                return k;
     }
 
     while (1) {
 
-       if (curtok == TOK_LBRACK) {
+       if (CurTok.Tok == TOK_LBRACK) {
 
            /* Array reference */
            k = arrayref (k, lval);
 
-       } else if (curtok == TOK_LPAREN) {
+       } else if (CurTok.Tok == TOK_LPAREN) {
 
            /* Function call. Skip the opening parenthesis */
            NextToken ();
@@ -1279,14 +1295,14 @@ static int hie11 (struct expent *lval)
            }
            k = 0;
 
-       } else if (curtok == TOK_DOT) {
+       } else if (CurTok.Tok == TOK_DOT) {
 
            if (!IsClassStruct (lval->e_tptr)) {
                Error ("Struct expected");
            }
            k = structref (0, lval);
 
-       } else if (curtok == TOK_PTR_REF) {
+       } else if (CurTok.Tok == TOK_PTR_REF) {
 
            tptr = lval->e_tptr;
            if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
@@ -1467,10 +1483,10 @@ static void unaryop (int tok, struct expent* lval)
 
     NextToken ();
     k = hie10 (lval);
-    if (k == 0 && lval->e_flags & E_MCONST) {
+    if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
        /* Value is constant */
        switch (tok) {
-           case TOK_MINUS: lval->e_const =     -lval->e_const; break;
+           case TOK_MINUS: lval->e_const = -lval->e_const;     break;
            case TOK_PLUS:                                      break;
            case TOK_COMP:  lval->e_const = ~lval->e_const;     break;
            default:        Internal ("Unexpected token: %d", tok);
@@ -1595,7 +1611,7 @@ static int hie10 (struct expent* lval)
     int k;
     type* t;
 
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_INC:
            pre_incdec (lval, g_inc);
@@ -1608,7 +1624,7 @@ static int hie10 (struct expent* lval)
        case TOK_PLUS:
        case TOK_MINUS:
        case TOK_COMP:
-           unaryop (curtok, lval);
+           unaryop (CurTok.Tok, lval);
            return 0;
 
        case TOK_BOOL_NOT:
@@ -1685,7 +1701,7 @@ static int hie10 (struct expent* lval)
     }
 
     k = hie11 (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
        case TOK_INC:
                    post_incdec (lval, k, g_inc);
            return 0;
@@ -1720,7 +1736,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
     k = hienext (lval);
 
     *UsedGen = 0;
-    while ((Gen = FindGen (curtok, ops)) != 0) {
+    while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
 
        /* Tell the caller that we handled it's ops */
        *UsedGen = 1;
@@ -1731,7 +1747,7 @@ static int hie_internal (GenDesc** ops,           /* List of generators */
        }
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1828,10 +1844,10 @@ static int hie_compare (GenDesc** ops,          /* List of generators */
 
     k = hienext (lval);
 
-    while ((Gen = FindGen (curtok, ops)) != 0) {
+    while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
 
        /* Remember the operator token, then skip it */
-               tok = curtok;
+               tok = CurTok.Tok;
        NextToken ();
 
        /* Get the lhs on stack */
@@ -1969,7 +1985,7 @@ static void parseadd (int k, struct expent* lval)
     flags = 0;
 
     /* Check for constness on both sides */
-    if (k == 0 && lval->e_flags == E_MCONST) {
+    if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
 
        /* The left hand side is a constant. Good. Get rhs */
                if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
@@ -1997,7 +2013,7 @@ static void parseadd (int k, struct expent* lval)
            }
 
                    /* Result is constant, condition codes not set */
-                   lval->e_test = E_MCONST;
+                   lval->e_test &= ~E_CC;
 
        } else {
 
@@ -2154,7 +2170,7 @@ static void parsesub (int k, struct expent* lval)
                rhst = lval2.e_tptr;
 
        /* Check left hand side */
-       if (k == 0 && lval->e_flags & E_MCONST) {
+       if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
 
            /* Both sides are constant, remove generated code */
            RemoveCode (Mark1);
@@ -2184,7 +2200,7 @@ static void parsesub (int k, struct expent* lval)
            }
 
            /* Result is constant, condition codes not set */
-           lval->e_flags = E_MCONST;
+           /* lval->e_flags = E_MCONST; ### */
            lval->e_test &= ~E_CC;
 
        } else {
@@ -2288,9 +2304,9 @@ static int hie8 (struct expent* lval)
 /* Process + and - binary operators. */
 {
     int k = hie9 (lval);
-    while (curtok == TOK_PLUS || curtok == TOK_MINUS) {
+    while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
 
-               if (curtok == TOK_PLUS) {
+               if (CurTok.Tok == TOK_PLUS) {
                    parseadd (k, lval);
                } else {
                    parsesub (k, lval);
@@ -2384,13 +2400,13 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
     struct expent lval2;
 
     k = hie2 (lval);
-    if (curtok == TOK_BOOL_AND) {
+    if (CurTok.Tok == TOK_BOOL_AND) {
 
                /* Tell our caller that we're evaluating a boolean */
                *BoolOp = 1;
 
                /* Get a label that we will use for false expressions */
-               lab = GetLabel ();
+               lab = GetLocalLabel ();
 
                /* If the expr hasn't set condition codes, set the force-test flag */
                if ((lval->e_test & E_CC) == 0) {
@@ -2404,7 +2420,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
                g_falsejump (CF_NONE, lab);
 
                /* Parse more boolean and's */
-               while (curtok == TOK_BOOL_AND) {
+               while (CurTok.Tok == TOK_BOOL_AND) {
 
                    /* Skip the && */
            NextToken ();
@@ -2417,7 +2433,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
            exprhs (CF_FORCECHAR, k, &lval2);
 
                    /* Do short circuit evaluation */
-           if (curtok == TOK_BOOL_AND) {
+           if (CurTok.Tok == TOK_BOOL_AND) {
                g_falsejump (CF_NONE, lab);
                    } else {
                        /* Last expression - will evaluate to true */
@@ -2426,7 +2442,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
                }
 
                /* Define the false jump label here */
-               g_defloclabel (lab);
+               g_defcodelabel (lab);
 
                /* Define the label */
                lval->e_flags = E_MEXPR;
@@ -2449,13 +2465,13 @@ static int hieOr (struct expent *lval)
     unsigned DoneLab;
 
     /* Get a label */
-    TrueLab = GetLabel ();
+    TrueLab = GetLocalLabel ();
 
     /* Call the next level parser */
     k = hieAnd (lval, TrueLab, &BoolOp);
 
     /* Any boolean or's? */
-    if (curtok == TOK_BOOL_OR) {
+    if (CurTok.Tok == TOK_BOOL_OR) {
 
        /* If the expr hasn't set condition codes, set the force-test flag */
                if ((lval->e_test & E_CC) == 0) {
@@ -2476,7 +2492,7 @@ static int hieOr (struct expent *lval)
        BoolOp = 1;
 
        /* while there's more expr */
-               while (curtok == TOK_BOOL_OR) {
+               while (CurTok.Tok == TOK_BOOL_OR) {
 
                    /* skip the || */
            NextToken ();
@@ -2495,7 +2511,7 @@ static int hieOr (struct expent *lval)
             */
 #if    0
 /* Seems this sometimes generates wrong code */
-           if (curtok == TOK_BOOL_OR && !AndOp) {
+           if (CurTok.Tok == TOK_BOOL_OR && !AndOp) {
                g_truejump (CF_NONE, TrueLab);
                    }
 #else
@@ -2509,12 +2525,12 @@ static int hieOr (struct expent *lval)
 
     /* If we really had boolean ops, generate the end sequence */
     if (BoolOp) {
-       DoneLab = GetLabel ();
+       DoneLab = GetLocalLabel ();
        g_getimmed (CF_INT | CF_CONST, 0, 0);   /* Load FALSE */
                g_falsejump (CF_NONE, DoneLab);
-       g_defloclabel (TrueLab);
+       g_defcodelabel (TrueLab);
        g_getimmed (CF_INT | CF_CONST, 1, 0);   /* Load TRUE */
-       g_defloclabel (DoneLab);
+       g_defcodelabel (DoneLab);
     }
     return k;
 }
@@ -2538,22 +2554,22 @@ static int hieQuest (struct expent *lval)
 
 
     k = hieOr (lval);
-    if (curtok == TOK_QUEST) {
+    if (CurTok.Tok == TOK_QUEST) {
        NextToken ();
        if ((lval->e_test & E_CC) == 0) {
            /* Condition codes not set, force a test */
            lval->e_test |= E_FORCETEST;
        }
        exprhs (CF_NONE, k, lval);
-       labf = GetLabel ();
+       labf = GetLocalLabel ();
        g_falsejump (CF_NONE, labf);
 
        /* Parse second and third expression */
        expression1 (&lval2);
-       labt = GetLabel ();
+       labt = GetLocalLabel ();
        ConsumeColon ();
        g_jump (labt);
-       g_defloclabel (labf);
+       g_defcodelabel (labf);
        expression1 (&lval3);
 
        /* Check if any conversions are needed, if so, do them.
@@ -2580,27 +2596,20 @@ static int hieQuest (struct expent *lval)
            /* Setup a new label so that the expr3 code will jump around
             * the type cast code for expr2.
             */
-                   labf = GetLabel ();         /* Get new label */
+                   labf = GetLocalLabel ();    /* Get new label */
            Mark1 = GetCodePos ();      /* Remember current position */
            g_jump (labf);              /* Jump around code */
 
            /* The jump for expr2 goes here */
-           g_defloclabel (labt);
+           g_defcodelabel (labt);
 
            /* Create the typecast code for expr2 */
            Mark2 = GetCodePos ();      /* Remember position */
            g_typecast (TypeOf (rtype), TypeOf (type2));
 
-           /* If the typecast did not produce code, remove the jump,
-            * otherwise output the label.
-            */
-           if (GetCodePos() == Mark2) {
-               RemoveCode (Mark1);     /* Remove code */
-           } else {
-               /* We have typecast code, output label */
-               g_defloclabel (labf);
-               labt = 0;               /* Mark other label as invalid */
-           }
+           /* Jump here around the typecase code. */
+           g_defcodelabel (labf);
+           labt = 0;           /* Mark other label as invalid */
 
        } else if (IsClassPtr (type2) && IsClassPtr (type3)) {
            /* Must point to same type */
@@ -2622,7 +2631,7 @@ static int hieQuest (struct expent *lval)
 
        /* If we don't have the label defined until now, do it */
        if (labt) {
-           g_defloclabel (labt);
+           g_defcodelabel (labt);
        }
 
        /* Setup the target expression */
@@ -2823,7 +2832,7 @@ static void Assignment (struct expent* lval)
 
     /* cc65 does not have full support for handling structs by value. Since
      * assigning structs is one of the more useful operations from this
-     * familiy, allow it here.
+     * family, allow it here.
      */
     if (IsClassStruct (ltype)) {
 
@@ -2891,7 +2900,7 @@ int hie1 (struct expent* lval)
     int k;
 
     k = hieQuest (lval);
-    switch (curtok) {
+    switch (CurTok.Tok) {
 
        case TOK_RPAREN:
        case TOK_SEMI:
@@ -2960,7 +2969,7 @@ int hie0 (struct expent *lval)
     int k;
 
     k = hie1 (lval);
-    while (curtok == TOK_COMMA) {
+    while (CurTok.Tok == TOK_COMMA) {
        NextToken ();
        k = hie1 (lval);
     }
@@ -3119,9 +3128,6 @@ void test (unsigned label, int cond)
     /* Load the value into the primary register */
     exprhs (CF_FORCECHAR, k, &lval);
 
-    /* Check for the closing brace */
-    ConsumeRParen ();
-
     /* Generate the jump */
     if (cond) {
        g_truejump (CF_NONE, label);
@@ -3130,10 +3136,13 @@ void test (unsigned label, int cond)
         * compiler itself is one big hack...): If a semicolon follows, we
         * don't have a statement and may omit the jump.
         */
-       if (curtok != TOK_SEMI) {
+       if (CurTok.Tok != TOK_SEMI) {
             g_falsejump (CF_NONE, label);
        }
     }
+
+    /* Check for the closing brace */
+    ConsumeRParen ();
 }