From: erikb Date: Wed, 13 Aug 1986 10:05:39 +0000 (+0000) Subject: revised the treatment of "e op= f" expression X-Git-Tag: release-5-5~5244 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a7e97524e42f4e5d2a1f2df2ceeec3c255f28f01;p=ack.git revised the treatment of "e op= f" expression --- diff --git a/lang/cem/cemcom/Files b/lang/cem/cemcom/Files index 9b7abae11..26fb953ff 100644 --- a/lang/cem/cemcom/Files +++ b/lang/cem/cemcom/Files @@ -75,6 +75,7 @@ statement.g stb.c storage.c storage.h +stmt.str struct.c struct.str switch.c diff --git a/lang/cem/cemcom/ch7.c b/lang/cem/cemcom/ch7.c index ab173731d..9c5819eda 100644 --- a/lang/cem/cemcom/ch7.c +++ b/lang/cem/cemcom/ch7.c @@ -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); - } -} diff --git a/lang/cem/cemcom/ch7bin.c b/lang/cem/cemcom/ch7bin.c index 217eecb55..970e8b764 100644 --- a/lang/cem/cemcom/ch7bin.c +++ b/lang/cem/cemcom/ch7bin.c @@ -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); diff --git a/lang/cem/cemcom/conversion.c b/lang/cem/cemcom/conversion.c index b74f779bf..7d6d47295 100644 --- a/lang/cem/cemcom/conversion.c +++ b/lang/cem/cemcom/conversion.c @@ -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; diff --git a/lang/cem/cemcom/dumpidf.c b/lang/cem/cemcom/dumpidf.c index af6f30938..361aa89a7 100644 --- a/lang/cem/cemcom/dumpidf.c +++ b/lang/cem/cemcom/dumpidf.c @@ -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: diff --git a/lang/cem/cemcom/eval.c b/lang/cem/cemcom/eval.c index b0f5f40c5..2ce3f8256 100644 --- a/lang/cem/cemcom/eval.c +++ b/lang/cem/cemcom/eval.c @@ -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 '(': { diff --git a/lang/cem/cemcom/field.c b/lang/cem/cemcom/field.c index 6245ac86f..747656ad6 100644 --- a/lang/cem/cemcom/field.c +++ b/lang/cem/cemcom/field.c @@ -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)<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