diff options
Diffstat (limited to 'linearize.c')
| -rw-r--r-- | linearize.c | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/linearize.c b/linearize.c index 2b1b2658..3dfe45c0 100644 --- a/linearize.c +++ b/linearize.c @@ -1615,8 +1615,7 @@ static pseudo_t linearize_short_conditional(struct entrypoint *ep, struct expres static pseudo_t linearize_conditional(struct entrypoint *ep, struct expression *expr, struct expression *cond, struct expression *expr_true, - struct expression *expr_false, - int logical) + struct expression *expr_false) { pseudo_t src1, src2; pseudo_t phi1, phi2; @@ -1632,19 +1631,11 @@ static pseudo_t linearize_conditional(struct entrypoint *ep, struct expression * set_activeblock(ep, bb_true); src1 = linearize_expression(ep, expr_true); - if (logical) { - src1 = add_convert_to_bool(ep, src1, expr_true->ctype); - src1 = cast_pseudo(ep, src1, &bool_ctype, expr->ctype); - } phi1 = alloc_phi(ep->active, src1, expr->ctype); add_goto(ep, merge); set_activeblock(ep, bb_false); src2 = linearize_expression(ep, expr_false); - if (logical) { - src2 = add_convert_to_bool(ep, src2, expr_false->ctype); - src2 = cast_pseudo(ep, src2, &bool_ctype, expr->ctype); - } phi2 = alloc_phi(ep->active, src2, expr->ctype); set_activeblock(ep, merge); @@ -1653,13 +1644,52 @@ static pseudo_t linearize_conditional(struct entrypoint *ep, struct expression * static pseudo_t linearize_logical(struct entrypoint *ep, struct expression *expr) { - struct expression *shortcut; + struct basic_block *merge; + pseudo_t phi1, phi2; - shortcut = alloc_const_expression(expr->pos, expr->op == SPECIAL_LOGICAL_OR); - shortcut->ctype = expr->ctype; - if (expr->op == SPECIAL_LOGICAL_OR) - return linearize_conditional(ep, expr, expr->left, shortcut, expr->right, 1); - return linearize_conditional(ep, expr, expr->left, expr->right, shortcut, 1); + if (!ep->active || !expr->left || !expr->right) + return VOID; + + if (expr->op == SPECIAL_LOGICAL_OR) { + struct expression *expr_false = expr->right; + struct basic_block *bb_true = alloc_basic_block(ep, expr->pos); + struct basic_block *bb_false = alloc_basic_block(ep, expr_false->pos); + pseudo_t src1, src2; + + merge = alloc_basic_block(ep, expr->pos); + linearize_cond_branch(ep, expr->left, bb_true, bb_false); + + set_activeblock(ep, bb_true); + src1 = value_pseudo(1); + phi1 = alloc_phi(ep->active, src1, expr->ctype); + add_goto(ep, merge); + + set_activeblock(ep, bb_false); + src2 = linearize_expression_to_bool(ep, expr_false); + src2 = cast_pseudo(ep, src2, &bool_ctype, expr->ctype); + phi2 = alloc_phi(ep->active, src2, expr->ctype); + } else { + struct expression *expr_true = expr->right; + struct basic_block *bb_true = alloc_basic_block(ep, expr_true->pos); + struct basic_block *bb_false = alloc_basic_block(ep, expr->pos); + pseudo_t src1, src2; + + merge = alloc_basic_block(ep, expr->pos); + linearize_cond_branch(ep, expr->left, bb_true, bb_false); + + set_activeblock(ep, bb_true); + src1 = linearize_expression_to_bool(ep, expr_true); + src1 = cast_pseudo(ep, src1, &bool_ctype, expr->ctype); + phi1 = alloc_phi(ep->active, src1, expr->ctype); + add_goto(ep, merge); + + set_activeblock(ep, bb_false); + src2 = value_pseudo(0); + phi2 = alloc_phi(ep->active, src2, expr->ctype); + } + + set_activeblock(ep, merge); + return add_join_conditional(ep, expr, phi1, phi2); } static pseudo_t linearize_compare(struct entrypoint *ep, struct expression *expr) @@ -1838,7 +1868,7 @@ static pseudo_t linearize_expression(struct entrypoint *ep, struct expression *e return linearize_short_conditional(ep, expr, expr->conditional, expr->cond_false); return linearize_conditional(ep, expr, expr->conditional, - expr->cond_true, expr->cond_false, 0); + expr->cond_true, expr->cond_false); case EXPR_COMMA: linearize_expression(ep, expr->left); |
