const out_val *gen_expr_assign_compound(const expr *e, out_ctx *octx) { /* int += float * lea int, cast up to float, add, cast down to int, store */ const out_val *saved_post = NULL, *addr_lhs, *rhs, *lhs, *result; addr_lhs = gen_expr(e->lhs, octx); out_val_retain(octx, addr_lhs); /* 2 */ if(e->assign_is_post){ out_val_retain(octx, addr_lhs); /* 3 */ saved_post = out_deref(octx, addr_lhs); /* addr_lhs=2, saved_post=1 */ } /* delay the dereference until after generating rhs. * this is fine, += etc aren't sequence points */ rhs = gen_expr(e->rhs, octx); /* here's the delayed dereference */ lhs = out_deref(octx, addr_lhs); /* addr_lhs=1 */ if(e->bits.compoundop.upcast_ty) lhs = out_cast(octx, lhs, e->bits.compoundop.upcast_ty, /*normalise_bool:*/1); result = out_op(octx, e->bits.compoundop.op, lhs, rhs); gen_op_trapv(e->tree_type, &result, octx, e->bits.compoundop.op); if(e->bits.compoundop.upcast_ty) /* need to cast back down to store */ result = out_cast(octx, result, e->tree_type, /*normalise_bool:*/1); if(!saved_post) out_val_retain(octx, result); out_store(octx, addr_lhs, result); if(!saved_post) return result; return saved_post; }
void gen_expr_assign_compound(expr *e) { /* int += float * lea int, cast up to float, add, cast down to int, store */ lea_expr(e->bits.compound_upcast ? expr_cast_child(e->lhs) : e->lhs); if(e->assign_is_post){ out_dup(); out_deref(); out_flush_volatile(); out_swap(); out_comment("saved for compound op"); } out_dup(); /* delay the dereference until after generating rhs. * this is fine, += etc aren't sequence points */ gen_expr(e->rhs); /* here's the delayed dereference */ out_swap(); out_deref(); if(e->bits.compound_upcast) out_cast(e->lhs->tree_type, /*normalise_bool:*/1); out_swap(); out_op(e->op); if(e->bits.compound_upcast) /* need to cast back down to store */ out_cast(e->tree_type, /*normalise_bool:*/1); out_store(); if(e->assign_is_post) out_pop(); }