depending on the constancy of the operands.
*/
+#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
+#define non_commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 0)
+
ch7bin(expp, oper, expr)
register struct expr **expp;
struct expr *expr;
break;
case '%':
case MODAB:
+ case ANDAB:
+ case XORAB:
+ case ORAB:
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
- fund = arithbalance(expp, oper, &expr);
- non_commutative_binop(expp, oper, expr);
- break;
+ /* Fall through */
case '/':
case DIVAB:
+ case TIMESAB:
fund = arithbalance(expp, oper, &expr);
non_commutative_binop(expp, oper, expr);
break;
+ case '&':
+ case '^':
+ case '|':
+ opnd2integral(expp, oper);
+ opnd2integral(&expr, oper);
+ /* Fall through */
case '*':
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 */
struct expr *etmp = expr;
non_commutative_binop(expp, oper, expr);
(*expp)->ex_type = int_type;
break;
- case '&':
- case '^':
- case '|':
- opnd2integral(expp, oper);
- opnd2integral(&expr, oper);
- 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);
opnd2test(&expr, oper);
if (is_cp_cst(*expp)) {
- struct expr *ex = *expp;
+ register struct expr *ex = *expp;
/* the following condition is a short-hand for
((oper == AND) && o1) || ((oper == OR) && !o1)
where o1 == (*expp)->VL_VALUE;
and ((oper == AND) || (oper == OR))
*/
- if ((oper == AND) == ((*expp)->VL_VALUE != (arith)0))
+ if ((oper == AND) == (ex->VL_VALUE != (arith)0))
*expp = expr;
else {
+ ex->ex_flags |= expr->ex_flags;
free_expression(expr);
*expp = intexpr((arith)((oper == AND) ? 0 : 1),
INT);
}
+ (*expp)->ex_flags |= ex->ex_flags;
free_expression(ex);
}
else
where o2 == expr->VL_VALUE
and ((oper == AND) || (oper == OR))
*/
- if ((oper == AND) == (expr->VL_VALUE != (arith)0))
+ if ((oper == AND) == (expr->VL_VALUE != (arith)0)) {
+ (*expp)->ex_flags |= expr->ex_flags;
free_expression(expr);
+ }
else {
if (oper == OR)
expr->VL_VALUE = (arith)1;
ch7cast(expp, CAST, int_type); /* result will be an integer expr */
}
-non_commutative_binop(expp, oper, expr)
+mk_binop(expp, oper, expr, commutative)
register struct expr **expp, *expr;
{
/* Constructs in *expp the operation indicated by the operands.
- "oper" is a non-commutative operator
+ "commutative" indicates wether "oper" is a commutative
+ operator.
*/
- if (is_cp_cst(expr) && is_cp_cst(*expp))
- cstbin(expp, oper, expr);
- else
- *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
-}
+ register struct expr *ex = *expp;
-commutative_binop(expp, oper, expr)
- register struct expr **expp, *expr;
-{
- /* Constructs in *expp the operation indicated by the operands.
- "oper" is a commutative operator
- */
- if (is_cp_cst(expr) && is_cp_cst(*expp))
+ if (is_cp_cst(expr) && is_cp_cst(ex))
cstbin(expp, oper, expr);
- else
- if ((*expp)->ex_depth > expr->ex_depth)
- *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
- else
- *expp = new_oper((*expp)->ex_type, expr, oper, *expp);
+ else {
+ *expp = (commutative && expr->ex_depth >= ex->ex_depth) ?
+ new_oper(ex->ex_type, expr, oper, ex) :
+ new_oper(ex->ex_type, ex, oper, expr);
+ }
}
pointer_arithmetic(expp1, oper, expp2)
if (tp->tp_fund == ERRONEOUS) /* stop immediately */
break;
+ if (tp->tp_fund == VOID)
+ gencode = 0;
switch (oper) {
case '+':
/* We have the following possibilities :
int + int, pointer + int, pointer + long,
long + long, double + double
*/
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode) {
switch (tp->tp_fund) {
case INT:
break;
case '-':
if (left == 0) { /* unary */
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode) {
switch (tp->tp_fund) {
case INT:
int - int, pointer - int, pointer - long,
pointer - pointer, long - long, double - double
*/
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (!gencode)
break;
switch (tp->tp_fund) {
break;
case '*':
if (left == 0) /* unary */
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
else { /* binary */
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
switch (tp->tp_fund) {
case INT:
}
break;
case '/':
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
switch (tp->tp_fund) {
case INT:
}
break;
case '%':
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
if (gencode)
if (tp->tp_unsigned)
C_rmi(tp->tp_size);
break;
case LEFT:
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
if (tp->tp_unsigned)
C_slu(tp->tp_size);
C_sli(tp->tp_size);
break;
case RIGHT:
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
if (tp->tp_unsigned)
C_sru(tp->tp_size);
case GREATEREQ:
case EQUAL:
case NOTEQUAL:
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode) {
/* The operands have the same type */
arith size = left->ex_type->tp_size;
case '|':
case '^':
/* both operands should have type int */
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode) {
arith size = tp->tp_size;
}
}
break;
- case '=':
+ case '=': {
+ int newcode = tp->tp_size > 0; /* CJ */
#ifndef NOBITFIELD
if (left->ex_type->tp_fund == FIELD) {
- eval_field(expr, code);
+ eval_field(expr, gencode);
break;
}
#endif NOBITFIELD
- EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
if (gencode)
C_dup(ATW(tp->tp_size));
if (left->ex_class != Value) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- store_block(tp->tp_size, tp->tp_align);
+ EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
+ if (newcode)
+ store_block(tp->tp_size, tp->tp_align);
}
- else
+ else if (newcode)
store_val(&(left->ex_object.ex_value),
left->ex_type);
+ }
break;
case PLUSAB:
case MINAB:
{
arith old_offset, tmp;
int compl; /* Complexity of left operand */
+ int newcode = left->ex_type->tp_size > 0; /* CJ */
#ifndef NOBITFIELD
if (left->ex_type->tp_fund == FIELD) {
- eval_field(expr, code);
+ eval_field(expr, gencode);
break;
}
#endif NOBITFIELD
- if (left->ex_class == Value) {
+ if (newcode && left->ex_class == Value) {
compl = 0; /* Value */
load_val(left, RVAL);
}
if (left->ex_depth == 1 && left->OP_OPER == ARROW) {
compl = 1; /* Value->sel */
ASSERT(left->OP_LEFT->ex_class == Value);
- EVAL(left, RVAL, TRUE, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, newcode, NO_LABEL, NO_LABEL);
}
else {
compl = 2; /* otherwise */
- tmp = tmp_pointer_var(&old_offset);
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_dup(pointer_size);
- C_lal(tmp);
- C_sti(pointer_size);
- C_loi(left->ex_type->tp_size);
- }
- conversion(left->ex_type, tp);
- if (gencode && (oper == POSTINCR || oper == POSTDECR))
- C_dup(tp->tp_size);
- EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
- assop(tp, oper);
- if (gencode && oper != POSTINCR && oper != POSTDECR)
- C_dup(tp->tp_size);
- conversion(tp, left->ex_type);
- if (compl == 0)
+ EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
+ if (newcode) {
+ tmp = tmp_pointer_var(&old_offset);
+ C_dup(pointer_size);
+ C_lal(tmp);
+ C_sti(pointer_size);
+ C_loi(left->ex_type->tp_size);
+ }
+ }
+ if (newcode) {
+ conversion(left->ex_type, tp);
+ if (gencode && (oper == POSTINCR ||
+ oper == POSTDECR))
+ C_dup(tp->tp_size);
+ }
+ EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
+ if (newcode) {
+ assop(tp, oper);
+ if (gencode && oper != POSTINCR &&
+ oper != POSTDECR)
+ C_dup(tp->tp_size);
+ conversion(tp, left->ex_type);
+ }
+ if (newcode && compl == 0)
store_val(&(left->ex_object.ex_value),
left->ex_type);
else
if (compl == 1) {
- EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_sti(left->ex_type->tp_size);
+ EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
+ if (newcode) C_sti(left->ex_type->tp_size);
}
- else {
+ else if (newcode) {
C_lal(tmp); /* always init'd */
C_loi(pointer_size);
C_sti(left->ex_type->tp_size);
while ( ex->ex_class == Oper &&
ex->OP_OPER == PARCOMMA
) {
- EVAL(ex->OP_RIGHT, RVAL, TRUE,
+ EVAL(ex->OP_RIGHT, RVAL,
+ ex->ex_type->tp_size > 0,
NO_LABEL, NO_LABEL);
ParSize += ATW(ex->ex_type->tp_size);
ex = ex->OP_LEFT;
}
- EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL);
+ EVAL(ex, RVAL, ex->ex_type->tp_size > 0,
+ NO_LABEL, NO_LABEL);
ParSize += ATW(ex->ex_type->tp_size);
}
if (left->ex_class == Value && left->VL_CLASS == Name) {
break;
}
case '.':
- EVAL(left, LVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, LVAL, gencode, NO_LABEL, NO_LABEL);
ASSERT(is_cp_cst(right));
if (gencode)
C_adp(right->VL_VALUE);
break;
case ARROW:
- EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
ASSERT(is_cp_cst(right));
if (gencode)
C_adp(right->VL_VALUE);
break;
case ',':
EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
break;
case '~':
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
C_com(tp->tp_size);
break;
EVAL(left, RVAL, TRUE, l_true, l_false);
C_df_ilb(l_true);
- EVAL(right->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
C_bra(l_end);
C_df_ilb(l_false);
- EVAL(right->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);
C_df_ilb(l_end);
break;
}
EVAL(left, RVAL, TRUE, l_maybe, false_label);
C_df_ilb(l_maybe);
- EVAL(right, RVAL, code, true_label,
+ EVAL(right, RVAL, gencode, true_label,
false_label);
}
break;
EVAL(left, RVAL, TRUE, true_label, l_maybe);
C_df_ilb(l_maybe);
- EVAL(right, RVAL, code, true_label,
+ EVAL(right, RVAL, gencode, true_label,
false_label);
}
break;
NO_LABEL);
}
else
- EVAL(right, RVAL, code, false_label,
+ EVAL(right, RVAL, gencode, false_label,
true_label);
break;
case INT2INT:
case FLOAT2INT:
case FLOAT2FLOAT:
#endif NOFLOAT
- EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
+ EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
conversion(right->ex_type, left->ex_type);
break;