revised the treatment of "e op= f" expression
authorerikb <none@none>
Wed, 13 Aug 1986 10:05:39 +0000 (10:05 +0000)
committererikb <none@none>
Wed, 13 Aug 1986 10:05:39 +0000 (10:05 +0000)
lang/cem/cemcom/Files
lang/cem/cemcom/ch7.c
lang/cem/cemcom/ch7bin.c
lang/cem/cemcom/conversion.c
lang/cem/cemcom/dumpidf.c
lang/cem/cemcom/eval.c
lang/cem/cemcom/field.c

index 9b7abae..26fb953 100644 (file)
@@ -75,6 +75,7 @@ statement.g
 stb.c
 storage.c
 storage.h
+stmt.str
 struct.c
 struct.str
 switch.c
index ab17373..9c5819e 100644 (file)
@@ -192,9 +192,6 @@ ch7cast(expp, oper, tp)
        if ((*expp)->ex_class == String)
                string2pointer(expp);
        oldtp = (*expp)->ex_type;
-       if (oldtp == tp)
-               {}                      /* life is easy */
-       else
 #ifndef NOBITFIELD
        if (oldtp->tp_fund == FIELD)    {
                field2arith(expp);
@@ -205,6 +202,9 @@ ch7cast(expp, oper, tp)
                ch7cast(expp, oper, tp->tp_up);
        else
 #endif NOBITFIELD
+       if (oldtp == tp)
+               {}                      /* life is easy */
+       else
        if (tp->tp_fund == VOID)        /* Easy again */
                (*expp)->ex_type = void_type;
        else
@@ -311,6 +311,17 @@ ch7asgn(expp, oper, expr)
        struct expr *expr;
 {
        /*      The assignment operators.
+               "f op= e" should be interpreted as
+               "f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
+               and not as "f = f op (typeof f)e".
+               Consider, for example, (i == 10) i *= 0.9; (i == 9), where
+               typeof i == int.
+               The resulting expression tree becomes:
+                               op=
+                               / \
+                              /   \
+                             f     (typeof (f op e))e
+               EVAL should however take care of evaluating (typeof (f op e))f
        */
        int fund = (*expp)->ex_type->tp_fund;
 
@@ -320,48 +331,30 @@ ch7asgn(expp, oper, expr)
                (*expp)->ex_depth = 99; /* no direct store/load at EVAL() */
                        /* what is 99 ??? DG */
        }
-       switch (oper)   {
-       case '=':
+       if (oper == '=') {
                ch7cast(&expr, oper, (*expp)->ex_type);
-               break;
-       case TIMESAB:
-       case DIVAB:
-       case MODAB:
-               check_arith_type(expp, oper);
-               any2arith(&expr, oper);
-               ch7cast(&expr, CAST, (*expp)->ex_type);
-               break;
-       case PLUSAB:
-       case MINAB:
-               any2arith(&expr, oper);
-               if (fund == POINTER)    {
-                       check_integral_type(&expr, oper);
-                       ch7bin(&expr, '*',
-                               intexpr(
-                                       size_of_type(
-                                               (*expp)->ex_type->tp_up,
-                                               "object"
-                                       ),
-                                       pa_type->tp_fund
-                               )
-                       );
-               }
-               else    {
-                       check_arith_type(expp, oper);
-                       ch7cast(&expr, CAST, (*expp)->ex_type);
+       }
+       else {  /* turn e into e' where typeof(e') = typeof (f op e) */
+               struct expr *extmp = intexpr(0, INT);
+
+               /* this is really $#@&*%$# ! */
+               extmp->ex_lvalue = 1;
+               extmp->ex_type = (*expp)->ex_type;
+               ch7bin(&extmp, oper, expr);
+               /* note that ch7bin creates a tree of the expression
+                       ((typeof (f op e))f op (typeof (f op e))e),
+                  where f ~ extmp and e ~ expr;
+                  we have to use (typeof (f op e))e
+                  Ch7bin does not create a tree if both operands
+                  were illegal or constants!
+               */
+               if (extmp->ex_class == Oper) {
+                       expr = extmp->OP_RIGHT;
+                       extmp->OP_RIGHT = NILEXPR;
+                       free_expression(extmp);
                }
-               break;
-       case LEFTAB:
-       case RIGHTAB:
-               check_integral_type(expp, oper);
-               ch7cast(&expr, oper, int_type);
-               break;
-       case ANDAB:
-       case XORAB:
-       case ORAB:
-               check_integral_type(expp, oper);
-               ch7cast(&expr, oper, (*expp)->ex_type);
-               break;
+               else
+                       expr = extmp;
        }
 #ifndef NOBITFIELD
        if (fund == FIELD)
@@ -369,6 +362,7 @@ ch7asgn(expp, oper, expr)
        else
 #endif NOBITFIELD
                *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+       (*expp)->OP_TYPE = expr->ex_type;       /* for EVAL() */
 }
 
 /*     Some interesting (?) questions answered.
@@ -393,18 +387,6 @@ is_integral_type(tp)
        }
 }
 
-check_integral_type(expp, oper)
-       struct expr **expp;
-{
-       register struct expr *expr = *expp;
-       
-       if (!is_integral_type(expr->ex_type))   {
-               expr_error(expr, "%s on non-integral type (%s)",
-                       symbol2str(oper), symbol2str(expr->ex_type->tp_fund));
-               erroneous2int(expp);
-       }
-}
-
 int
 is_arith_type(tp)
        struct type *tp;
@@ -426,15 +408,3 @@ is_arith_type(tp)
                return 0;
        }
 }
-
-check_arith_type(expp, oper)
-       struct expr **expp;
-{
-       register struct expr *expr = *expp;
-       
-       if (!is_arith_type(expr->ex_type))      {
-               expr_error(expr, "%s on non-arithmetical type (%s)",
-                       symbol2str(oper), symbol2str(expr->ex_type->tp_fund));
-               erroneous2int(expp);
-       }
-}
index 217eecb..970e8b7 100644 (file)
@@ -24,6 +24,7 @@ ch7bin(expp, oper, expr)
        struct expr *expr;
 {
        /*      apply binary operator oper between *expp and expr.
+               NB: don't swap operands if op is one of the op= operators!!!
        */
        any2opnd(expp, oper);
        any2opnd(&expr, oper);
@@ -79,15 +80,24 @@ ch7bin(expp, oper, expr)
                *expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
                break;
        case '%':
+       case MODAB:
+/*** NB  "not float" means "integral" !!!
                fund = arithbalance(expp, oper, &expr);
                if (fund == DOUBLE)     {
-                       expr_error(*expp, "floating operand to %%");
+                       expr_error(*expp, "floating operand to %s", 
+                               symbol2str(oper));
                        erroneous2int(expp);
                }
                else
                        non_commutative_binop(expp, oper, expr);
+***/
+               opnd2integral(expp, oper);
+               opnd2integral(&expr, oper);
+               fund = arithbalance(expp, oper, &expr);
+               non_commutative_binop(expp, oper, expr);
                break;
        case '/':
+       case DIVAB:
                fund = arithbalance(expp, oper, &expr);
                non_commutative_binop(expp, oper, expr);
                break;
@@ -95,6 +105,10 @@ ch7bin(expp, oper, expr)
                fund = arithbalance(expp, oper, &expr);
                commutative_binop(expp, oper, expr);
                break;
+       case TIMESAB:
+               fund = arithbalance(expp, oper, &expr);
+               non_commutative_binop(expp, oper, expr);
+               break;
        case '+':
                if (expr->ex_type->tp_fund == POINTER)  {
                        /* swap operands */
@@ -102,6 +116,8 @@ ch7bin(expp, oper, expr)
                        expr = *expp;
                        *expp = etmp;
                }
+               /*FALLTHROUGH*/
+       case PLUSAB:
                if ((*expp)->ex_type->tp_fund == POINTER)       {
                        pointer_arithmetic(expp, oper, &expr);
                        if (    expr->ex_type->tp_size !=
@@ -113,10 +129,14 @@ ch7bin(expp, oper, expr)
                }
                else    {
                        fund = arithbalance(expp, oper, &expr);
-                       commutative_binop(expp, oper, expr);
+                       if (oper == '+')
+                               commutative_binop(expp, oper, expr);
+                       else
+                               non_commutative_binop(expp, oper, expr);
                }
                break;
        case '-':
+       case MINAB:
                if ((*expp)->ex_type->tp_fund == POINTER)       {
                        if (expr->ex_type->tp_fund == POINTER)
                                pntminuspnt(expp, oper, expr);
@@ -131,7 +151,9 @@ ch7bin(expp, oper, expr)
                }
                break;
        case LEFT:
+       case LEFTAB:
        case RIGHT:
+       case RIGHTAB:
                opnd2integral(expp, oper);
                opnd2integral(&expr, oper);
                ch7cast(&expr, oper, int_type); /* leftop should be int */
@@ -152,9 +174,17 @@ ch7bin(expp, oper, expr)
        case '|':
                opnd2integral(expp, oper);
                opnd2integral(&expr, oper);
-               fund = arithbalance(expp, oper, &expr); /* <=== */
+               fund = arithbalance(expp, oper, &expr);
                commutative_binop(expp, oper, expr);
                break;
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               opnd2integral(expp, oper);
+               opnd2integral(&expr, oper);
+               fund = arithbalance(expp, oper, &expr);
+               non_commutative_binop(expp, oper, expr);
+               break;
        case AND:
        case OR:
                opnd2test(expp, oper);
index b74f779..7d6d472 100644 (file)
@@ -115,6 +115,7 @@ fundamental(tp)
        case CHAR:
        case SHORT:
        case INT:
+       case ERRONEOUS:
        case LONG:
        case ENUM:
                return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
index af6f309..361aa89 100644 (file)
@@ -271,9 +271,10 @@ type2str(tp)
                        if (tp->tp_field)       {
                                struct field *fd = tp->tp_field;
                                
-                               sprint(buf, "%s [s=%ld,w=%ld]", buf,
+                               sprint(buf, "%s [s=%ld,w=%ld] of ", buf,
                                        fd->fd_shift, fd->fd_width);
                        }
+                       else
 #endif NOBITFIELD
                        ops = 0;
                        break;
@@ -367,7 +368,10 @@ p1_expr(lvl, expr)
                o = &expr->ex_object.ex_oper;
                print("\n");
                p1_expr(lvl+1, o->op_left);
-               p1_indent(lvl); print("%s\n", symbol2str(o->op_oper));
+               p1_indent(lvl);
+               print("%s <%s>\n", symbol2str(o->op_oper),
+                       type2str(o->op_type)
+               );
                p1_expr(lvl+1, o->op_right);
                break;
        case Type:
index b0f5f40..2ce3f82 100644 (file)
@@ -389,27 +389,33 @@ EVAL(expr, val, code, true_label, false_label)
                                C_sti(pointer_size);
                                C_lal(tmpvar);
                                C_loi(pointer_size);
-                               C_loi(tp->tp_size);
+                               C_loi(leftop->ex_type->tp_size);
+                               conversion(leftop->ex_type, tp);
                                EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
                                assop(tp, oper);
+                               conversion(tp, leftop->ex_type);
                                if (gencode)
-                                       C_dup(roundup(tp->tp_size));
+                                       C_dup(roundup(leftop->ex_type->tp_size));
                                C_lal(tmpvar);
                                C_loi(pointer_size);
-                               C_sti(tp->tp_size);
+                               C_sti(leftop->ex_type->tp_size);
                                free_tmp_var(old_offset);
                        }
                        else    {
                                load_val(leftop, RVAL);
+                               conversion(leftop->ex_type, tp);
                                EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
                                assop(tp, oper);
+                               conversion(tp, leftop->ex_type);
                                if (gencode)
-                                       C_dup(roundup(tp->tp_size));
+                                       C_dup(roundup(leftop->ex_type->tp_size));
                                store_val(
                                        &(leftop->ex_object.ex_value),
                                        leftop->ex_type
                                );
                        }
+                       if (gencode)
+                               conversion(leftop->ex_type, expr->ex_type);
                        break;
                case '(':
                {
index 6245ac8..747656a 100644 (file)
@@ -40,13 +40,16 @@ eval_field(expr, code)
        struct type *tp = leftop->ex_type->tp_up;
        arith old_offset, tmpvar;
 
-       /*      The type in which the bitfield arithmetic is done:
+       /*      The type in which the bitfield arithmetic is done;
+               AND IN WHICH BITFIELDS ARE STORED!
        */
        struct type *atype = tp->tp_unsigned ? uword_type : word_type;
        arith asize = atype->tp_size;
 
-       ASSERT(leftop->ex_type->tp_fund == FIELD);
+       /* First some assertions to be sure that the rest is legal */
        ASSERT(asize == word_size);     /* make sure that C_loc() is legal */
+       ASSERT(leftop->ex_type->tp_fund == FIELD);
+
        leftop->ex_type = atype;        /* this is cheating but it works... */
 
        /*      Note that op is either an assignment operator or an increment/
@@ -55,6 +58,8 @@ eval_field(expr, code)
        if (op == '=') {
                /*      F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f)
                */
+               ASSERT(tp == rightop->ex_type);
+
                EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
                conversion(tp, atype);
                C_loc(fd->fd_mask);
@@ -71,10 +76,7 @@ eval_field(expr, code)
                        load_val(leftop, RVAL);
                        C_and(asize);
                        C_ior(asize);
-                       store_val(
-                               &(leftop->ex_object.ex_value),
-                               leftop->ex_type
-                       );
+                       store_val(&(leftop->ex_object.ex_value), atype);
                }
                else    {                       /* complex case */
                        tmpvar = tmp_pointer_var(&old_offset);
@@ -114,16 +116,19 @@ eval_field(expr, code)
                C_and(asize);
                if (code == TRUE && (op == POSTINCR || op == POSTDECR))
                        C_dup(asize);
+
+               /* the 'op' operation: */
+               conversion(atype, rightop->ex_type);
                EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
-               conversion(tp, atype);
-               /* generate code for the operator */
                if (op == PLUSPLUS || op == POSTINCR)
-                       assop(atype, PLUSAB);
+                       assop(rightop->ex_type, PLUSAB);
                else
                if (op == MINMIN || op == POSTDECR)
-                       assop(atype, MINAB);
+                       assop(rightop->ex_type, MINAB);
                else
-                       assop(atype, op);
+                       assop(rightop->ex_type, op);
+               conversion(rightop->ex_type, atype);
+
                C_loc(fd->fd_mask);
                C_and(asize);
                if (code == TRUE && op != POSTINCR && op != POSTDECR)
@@ -138,10 +143,7 @@ eval_field(expr, code)
                        load_val(leftop, RVAL);
                        C_and(asize);
                        C_ior(asize);
-                       store_val(
-                               &(leftop->ex_object.ex_value),
-                               leftop->ex_type
-                       );
+                       store_val(&(leftop->ex_object.ex_value), atype);
                }
                else    {
                        C_lal(tmpvar);
@@ -168,7 +170,7 @@ eval_field(expr, code)
                        C_loc(shift);
                        C_sri(asize);
                }
-               conversion(atype, tp);
+               conversion(atype, expr->ex_type);
        }
 }
 #endif NOBITFIELD