stb.c
storage.c
storage.h
+stmt.str
struct.c
struct.str
switch.c
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);
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
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;
(*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)
else
#endif NOBITFIELD
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+ (*expp)->OP_TYPE = expr->ex_type; /* for EVAL() */
}
/* Some interesting (?) questions answered.
}
}
-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;
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);
- }
-}
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);
*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;
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 */
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 !=
}
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);
}
break;
case LEFT:
+ case LEFTAB:
case RIGHT:
+ case RIGHTAB:
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
ch7cast(&expr, oper, int_type); /* leftop should be int */
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);
case CHAR:
case SHORT:
case INT:
+ case ERRONEOUS:
case LONG:
case ENUM:
return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
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;
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:
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 '(':
{
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/
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);
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);
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)
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);
C_loc(shift);
C_sri(asize);
}
- conversion(atype, tp);
+ conversion(atype, expr->ex_type);
}
}
#endif NOBITFIELD