X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_dw.c;h=c8d013266db743c13429f30833ced8b97da5ae02;hb=c378db2a15d92914dcbe4c6bf08a6b4558ecc708;hp=ddf9f43b55abef6e149c8e2a9f5cb96fc05f5076;hpb=28fdeeecc640572feeccca0107e58ffad94978fb;p=libfirm diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index ddf9f43b5..c8d013266 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -59,7 +59,7 @@ static set *conv_types; static pmap *lowered_type; /** The types for the binop and unop intrinsics. */ -static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *tp_s, *tp_u; +static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *shiftop_tp_u, *shiftop_tp_s, *tp_s, *tp_u; /** the debug handle */ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) @@ -103,7 +103,8 @@ enum lower_flags { typedef struct _lower_env_t { node_entry_t **entries; /**< entries per node */ struct obstack obst; /**< an obstack holding the temporary data */ - tarval *tv_mode_bytes; /**< a tarval containing the number of bits in the lowered modes */ + tarval *tv_mode_bytes; /**< a tarval containing the number of bytes in the lowered modes */ + tarval *tv_mode_bits; /**< a tarval containing the number of bits in the lowered modes */ pdeq *waitq; /**< a wait queue of all nodes that must be handled later */ pmap *proj_2_block; /**< a map from ProjX to its destination blocks */ const lwrdw_param_t *params; /**< transformation parameter */ @@ -345,7 +346,7 @@ static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) { tv_l = tarval_convert_to(tv, mode); low = new_rd_Const(dbg, current_ir_graph, block, mode, tv_l); - tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bytes), mode); + tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode); high = new_rd_Const(dbg, current_ir_graph, block, mode, tv_h); idx = get_irn_idx(node); @@ -850,6 +851,51 @@ static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) { env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); } +/** + * Translate a Shiftop. + * + * Create an intrinsic Call. + */ +static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) { + ir_node *block, *irn; + ir_node *in[3]; + dbg_info *dbg; + ir_type *mtp; + int idx; + node_entry_t *entry; + + irn = get_binop_left(node); + entry = env->entries[get_irn_idx(irn)]; + assert(entry); + + if (! entry->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } + + in[0] = entry->low_word; + in[1] = entry->high_word; + + /* The shift count is always mode_Iu in firm, so there is no need for lowering */ + in[2] = get_binop_right(node); + + dbg = get_irn_dbg_info(node); + block = get_nodes_block(node); + + mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u; + irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env); + irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph), + irn, 3, in, mtp); + set_irn_pinned(irn, get_irn_pinned(node)); + irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result); + + idx = get_irn_idx(node); + assert(idx < env->n_entries); + env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, mode, 0); + env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); +} + /** * Translate an Unop. * @@ -1434,6 +1480,8 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { else set_method_param_type(res, n_param++, tp); } + else + set_method_param_type(res, n_param++, tp); } for (i = n_res = 0; i < r; ++i) { ir_type *tp = get_method_res_type(mtp, i); @@ -1452,6 +1500,8 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { else set_method_res_type(res, n_res++, tp); } + else + set_method_res_type(res, n_res++, tp); } set_lowered_type(mtp, res); pmap_insert(lowered_type, mtp, res); @@ -1897,7 +1947,6 @@ void lower_dw_ops(const lwrdw_param_t *param) return; FIRM_DBG_REGISTER(dbg, "firm.lower.dw"); - firm_dbg_set_mask(dbg, SET_LEVEL_2); assert(2 * get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->high_signed)); assert(2 * get_mode_size_bits(param->low_unsigned) == get_mode_size_bits(param->high_unsigned)); @@ -1920,7 +1969,6 @@ void lower_dw_ops(const lwrdw_param_t *param) if (! binop_tp_u) { binop_tp_u = new_type_method(IDENT("binop_u_intrinsic"), 4, 2); - set_method_param_type(binop_tp_u, 0, tp_u); set_method_param_type(binop_tp_u, 1, tp_u); set_method_param_type(binop_tp_u, 2, tp_u); @@ -1937,6 +1985,23 @@ void lower_dw_ops(const lwrdw_param_t *param) set_method_res_type(binop_tp_s, 0, tp_s); set_method_res_type(binop_tp_s, 1, tp_s); } + if (! shiftop_tp_u) { + shiftop_tp_u = new_type_method(IDENT("shiftop_u_intrinsic"), 3, 2); + set_method_param_type(shiftop_tp_u, 0, tp_u); + set_method_param_type(shiftop_tp_u, 1, tp_u); + set_method_param_type(shiftop_tp_u, 2, tp_u); + set_method_res_type(shiftop_tp_u, 0, tp_u); + set_method_res_type(shiftop_tp_u, 1, tp_u); + } + if (! shiftop_tp_s) { + shiftop_tp_s = new_type_method(IDENT("shiftop_s_intrinsic"), 3, 2); + set_method_param_type(shiftop_tp_s, 0, tp_s); + set_method_param_type(shiftop_tp_s, 1, tp_s); + /* beware: shift count is always mode_Iu */ + set_method_param_type(shiftop_tp_s, 2, tp_u); + set_method_res_type(shiftop_tp_s, 0, tp_s); + set_method_res_type(shiftop_tp_s, 1, tp_s); + } if (! unop_tp_u) { unop_tp_u = new_type_method(IDENT("unop_u_intrinsic"), 2, 2); set_method_param_type(unop_tp_u, 0, tp_u); @@ -1953,6 +2018,7 @@ void lower_dw_ops(const lwrdw_param_t *param) } lenv.tv_mode_bytes = new_tarval_from_long(get_mode_size_bytes(param->low_unsigned), mode_Iu); + lenv.tv_mode_bits = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), mode_Iu); lenv.waitq = new_pdeq(); lenv.params = param; @@ -1962,6 +2028,7 @@ void lower_dw_ops(const lwrdw_param_t *param) #define LOWER2(op, fkt) op_##op->ops.generic = (op_func)fkt #define LOWER(op) LOWER2(op, lower_##op) #define LOWER_BIN(op) LOWER2(op, lower_Binop) +#define LOWER_SHIFT(op) LOWER2(op, lower_Shiftop) #define LOWER_UN(op) LOWER2(op, lower_Unop) LOWER(Load); @@ -1981,10 +2048,10 @@ void lower_dw_ops(const lwrdw_param_t *param) LOWER_BIN(Add); LOWER_BIN(Sub); LOWER_BIN(Mul); - LOWER_BIN(Shl); - LOWER_BIN(Shr); - LOWER_BIN(Shrs); - LOWER_BIN(Rot); + LOWER_SHIFT(Shl); + LOWER_SHIFT(Shr); + LOWER_SHIFT(Shrs); + LOWER_SHIFT(Rot); LOWER_UN(Minus); LOWER(DivMod); LOWER(Div);