aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.c
diff options
Diffstat (limited to 'linearize.c')
-rw-r--r--linearize.c64
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);