revised the treatment of "e op= f" expression
This commit is contained in:
parent
8217bef1eb
commit
a7e97524e4
7 changed files with 106 additions and 92 deletions
|
@ -75,6 +75,7 @@ statement.g
|
|||
stb.c
|
||||
storage.c
|
||||
storage.h
|
||||
stmt.str
|
||||
struct.c
|
||||
struct.str
|
||||
switch.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 { /* 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);
|
||||
}
|
||||
else {
|
||||
check_arith_type(expp, oper);
|
||||
ch7cast(&expr, CAST, (*expp)->ex_type);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 '(':
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue