X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_mode_b.c;h=9d42f7ca8e605f8bc8475a489e6a9beed752f1df;hb=30d3b0bd1a6cfec7d24c23fee7e63108664927d0;hp=13aa55e649f8b9a948556f7fdfb65822451b89e0;hpb=7b1dc982307121e3a7ddf3796bf339b9bdb6ad55;p=libfirm diff --git a/ir/lower/lower_mode_b.c b/ir/lower/lower_mode_b.c index 13aa55e64..9d42f7ca8 100644 --- a/ir/lower/lower_mode_b.c +++ b/ir/lower/lower_mode_b.c @@ -38,6 +38,7 @@ static ir_mode *lowered_mode = NULL; static int lower_direct_cmp = 0; +static ir_type *lowered_type = NULL; static ir_node *create_not(dbg_info *dbgi, ir_node *node) { @@ -49,6 +50,47 @@ static ir_node *create_not(dbg_info *dbgi, ir_node *node) return new_rd_Eor(dbgi, irg, block, node, one, lowered_mode); } +static ir_node *create_convb(ir_node *node) +{ + ir_graph *irg = current_ir_graph; + ir_node *block = get_nodes_block(node); + ir_node *conv = new_rd_Conv(NULL, irg, block, node, mode_b); + + return conv; +} + +static ir_type *create_lowered_type(void) +{ + if(lowered_type == NULL) { + lowered_type = new_type_primitive(new_id_from_str("__lowered_mode_b"), + lowered_mode); + } + return lowered_type; +} + +static void adjust_method_type(ir_type *method_type) +{ + int i; + int n_params; + int n_res; + + n_params = get_method_n_params(method_type); + for(i = 0; i < n_params; ++i) { + ir_type *param = get_method_param_type(method_type, i); + if(get_type_mode(param) == mode_b) { + set_method_param_type(method_type, i, create_lowered_type()); + } + } + + n_res = get_method_n_ress(method_type); + for(i = 0; i < n_res; ++i) { + ir_type *res_type = get_method_res_type(method_type, i); + if(get_type_mode(res_type) == mode_b) { + set_method_res_type(method_type, i, create_lowered_type()); + } + } +} + static ir_node *lower_node(ir_node *node) { ir_graph *irg = current_ir_graph; @@ -67,7 +109,7 @@ static ir_node *lower_node(ir_node *node) if(op == op_Phi) { int i, arity; ir_node **in; - ir_node *unknown; + ir_node *unknown, *new_phi; arity = get_irn_arity(node); in = alloca(arity * sizeof(in[0])); @@ -75,7 +117,7 @@ static ir_node *lower_node(ir_node *node) for(i = 0; i < arity; ++i) { in[i] = unknown; } - ir_node *new_phi = new_rd_Phi(dbgi, irg, block, arity, in, + new_phi = new_rd_Phi(dbgi, irg, block, arity, in, lowered_mode); set_irn_link(node, new_phi); @@ -101,6 +143,7 @@ static ir_node *lower_node(ir_node *node) set_irn_n(copy, i, low_in); } set_irn_mode(copy, lowered_mode); + set_irn_link(node, copy); return copy; } @@ -120,7 +163,7 @@ static ir_node *lower_node(ir_node *node) ir_node *v_false = get_Psi_default(node); ir_node *low_v_false = lower_node(v_false); - ir_node *and0 = new_rd_And(dbgi, irg, block, cond, low_v_true, + ir_node *and0 = new_rd_And(dbgi, irg, block, low_cond, low_v_true, lowered_mode); ir_node *not_cond = create_not(dbgi, low_cond); @@ -139,11 +182,12 @@ static ir_node *lower_node(ir_node *node) ir_node *one = new_d_Const(dbgi, lowered_mode, tv_one); tarval *tv_zero = get_tarval_null(lowered_mode); ir_node *zero = new_d_Const(dbgi, lowered_mode, tv_zero); - ir_mode *mode = get_irn_mode(node); + ir_node *pred = get_Conv_op(node); + ir_mode *mode = get_irn_mode(pred); tarval *tv_zeroc = get_tarval_null(mode); ir_node *zero_cmp = new_d_Const(dbgi, mode, tv_zeroc); - ir_node *cmp = new_rd_Cmp(dbgi, irg, block, node, zero_cmp); + ir_node *cmp = new_rd_Cmp(dbgi, irg, block, pred, zero_cmp); ir_node *proj = new_rd_Proj(dbgi, irg, block, cmp, mode_b, pn_Cmp_Lg); ir_node *vals[2] = { one, zero }; @@ -154,18 +198,18 @@ static ir_node *lower_node(ir_node *node) return psi; } if(op == op_Proj) { - ir_node *pred = get_Proj_pred(node); + ir_node *pred = get_Proj_pred(node); - assert(!is_Load(pred)); if(is_Cmp(pred)) { - ir_mode *mode = get_irn_mode(pred); ir_node *left = get_Cmp_left(pred); ir_node *right = get_Cmp_right(pred); + ir_mode *mode = get_irn_mode(left); - if(get_mode_size_bits(mode) < get_mode_size_bits(lowered_mode) - || classify_Const(right) == CNST_NULL) { + if ((mode_is_int(mode) || mode_is_reference(mode)) && ( + get_mode_size_bits(mode) < get_mode_size_bits(lowered_mode) || + (is_Const(right) && is_Const_null(right)) + )) { int pnc = get_Proj_proj(node); - ir_node *res = NULL; int need_not = 0; ir_node *a = NULL; ir_node *b = NULL; @@ -225,6 +269,17 @@ static ir_node *lower_node(ir_node *node) set_irn_link(node, psi); return psi; } + } else if(is_Proj(pred) && is_Call(get_Proj_pred(pred))) { + ir_type *type = get_Call_type(get_Proj_pred(pred)); + adjust_method_type(type); + set_irn_mode(node, lowered_mode); + return node; + } else if(is_Proj(pred) && is_Start(get_Proj_pred(pred))) { + ir_entity *entity = get_irg_entity(irg); + ir_type *type = get_entity_type(entity); + adjust_method_type(type); + set_irn_mode(node, lowered_mode); + return node; } panic("unexpected projb: %+F (pred: %+F)", node, pred); @@ -247,15 +302,6 @@ static ir_node *lower_node(ir_node *node) panic("didn't expect %+F to have mode_b", node); } -static ir_node *create_convb(ir_node *node) -{ - ir_graph *irg = current_ir_graph; - ir_node *block = get_nodes_block(node); - ir_node *conv = new_rd_Conv(NULL, irg, block, node, mode_b); - - return conv; -} - static void lower_mode_b_walker(ir_node *node, void *env) { int i, arity; @@ -280,7 +326,17 @@ static void lower_mode_b_walker(ir_node *node, void *env) } lowered_in = lower_node(in); - lowered_in = create_convb(lowered_in); + + if(is_Return(node)) { + ir_entity *entity = get_irg_entity(current_ir_graph); + ir_type *type = get_entity_type(entity); + adjust_method_type(type); + } else if(is_Call(node)) { + ir_type *type = get_Call_type(node); + adjust_method_type(type); + } else { + lowered_in = create_convb(lowered_in); + } set_irn_n(node, i, lowered_in); } } @@ -296,6 +352,7 @@ void ir_lower_mode_b(ir_graph *irg, ir_mode *mode, int do_lower_direct_cmp) lowered_mode = mode; lower_direct_cmp = do_lower_direct_cmp; set_using_irn_link(irg); - irg_walk_graph(irg, clear_links, lower_mode_b_walker, NULL); + irg_walk_graph(irg, clear_links, NULL, NULL); + irg_walk_graph(irg, lower_mode_b_walker, NULL, NULL); clear_using_irn_link(irg); }