void default_dbg_info_merge_pair(ir_node *nw, ir_node *old, dbg_action info) { dbg_info *new_db = get_irn_dbg_info(nw); (void) info; if (new_db == NULL) set_irn_dbg_info(nw, get_irn_dbg_info(old)); }
void default_dbg_info_merge_sets(ir_node *const *new_nodes, int n_new_nodes, ir_node *const *old_nodes, int n_old_nodes, dbg_action info) { (void) info; if (n_old_nodes == 1) { dbg_info *old_db = get_irn_dbg_info(old_nodes[0]); int i; for (i = 0; i < n_new_nodes; ++i) if (get_irn_dbg_info(new_nodes[i]) == NULL) set_irn_dbg_info(new_nodes[i], old_db); } }
ir_node *be_transform_phi(ir_node *node, const arch_register_req_t *req) { ir_node *block = be_transform_nodes_block(node); ir_graph *irg = get_irn_irg(block); dbg_info *dbgi = get_irn_dbg_info(node); /* phi nodes allow loops, so we use the old arguments for now * and fix this later */ ir_node **ins = get_irn_in(node)+1; int arity = get_irn_arity(node); ir_mode *mode = req->cls != NULL ? req->cls->mode : get_irn_mode(node); ir_node *phi = new_ir_node(dbgi, irg, block, op_Phi, mode, arity, ins); copy_node_attr(irg, node, phi); backend_info_t *info = be_get_info(phi); info->in_reqs = be_allocate_in_reqs(irg, arity); for (int i = 0; i < arity; ++i) { info->in_reqs[i] = req; } arch_set_irn_register_req_out(phi, 0, req); be_enqueue_preds(node); return phi; }
ir_node *be_duplicate_node(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_graph *irg = env.irg; dbg_info *dbgi = get_irn_dbg_info(node); ir_mode *mode = get_irn_mode(node); ir_op *op = get_irn_op(node); ir_node *new_node; int arity = get_irn_arity(node); if (op->opar == oparity_dynamic) { new_node = new_ir_node(dbgi, irg, block, op, mode, -1, NULL); for (int i = 0; i < arity; ++i) { ir_node *in = get_irn_n(node, i); in = be_transform_node(in); add_irn_n(new_node, in); } } else { ir_node **ins = ALLOCAN(ir_node*, arity); for (int i = 0; i < arity; ++i) { ir_node *in = get_irn_n(node, i); ins[i] = be_transform_node(in); } new_node = new_ir_node(dbgi, irg, block, op, mode, arity, ins); } copy_node_attr(irg, node, new_node); be_duplicate_deps(node, new_node); new_node->node_nr = node->node_nr; return new_node; }
/* * The 64-bit version of libgcc does not contain some builtin * functions for 32-bit values (__<builtin>si2) anymore. */ static void widen_builtin(ir_node *node) { ir_type *mtp = get_Builtin_type(node); ir_type *arg1 = get_method_param_type(mtp, 0); // Nothing to do, if argument size is at least machine size. if (get_type_size(arg1) >= ir_target_pointer_size()) return; // Only touch builtins with no 32-bit version. ir_builtin_kind kind = get_Builtin_kind(node); if (kind != ir_bk_clz && kind != ir_bk_ctz && kind != ir_bk_ffs && kind != ir_bk_parity && kind != ir_bk_popcount) { return; } ir_mode *target_mode = get_reference_offset_mode(mode_P); dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *op = get_irn_n(node, n_Builtin_max + 1); ir_node *conv = new_rd_Conv(dbgi, block, op, target_mode); set_irn_n(node, n_Builtin_max + 1, conv); ir_type *new_arg1 = get_type_for_mode(target_mode); ir_type *new_result = get_method_res_type(mtp, 0); ir_type *new_type = new_type_method(1, 1, false, cc_cdecl_set, mtp_no_property); set_method_param_type(new_type, 0, new_arg1); set_method_res_type(new_type, 0, new_result); set_Builtin_type(node, new_type); }
/** * lower Alloca nodes to allocate "bytes" instead of a certain type */ static void lower_alloca_free(ir_node *node, void *data) { (void) data; if (is_Alloc(node)) { } else if (is_Proj(node)) { ir_node *proj_pred = get_Proj_pred(node); if (is_Alloc(proj_pred)) { transform_Proj_Alloc(node); } return; } else { return; } if (!ir_nodeset_insert(&transformed, node)) return; if (stack_alignment <= 1) return; ir_node *const size = get_Alloc_size(node); ir_node *const mem = get_Alloc_mem(node); ir_node *const block = get_nodes_block(node); dbg_info *const dbgi = get_irn_dbg_info(node); ir_node *const new_size = adjust_alloc_size(dbgi, size, block); ir_node *const new_node = new_rd_Alloc(dbgi, block, mem, new_size, 1); ir_nodeset_insert(&transformed, new_node); if (new_node != node) exchange(node, new_node); }
static void be_vdiagnosticf(ir_node const *const node, char const *const kind, char const *const fmt, va_list ap) { FILE *const out = stderr; if (node) { ir_fprintf(out, "%+F", node); dbg_info *const dbgi = get_irn_dbg_info(node); src_loc_t const loc = ir_retrieve_dbg_info(dbgi); if (loc.file) { ir_fprintf(out, " (%s", loc.file); if (loc.line != 0) { ir_fprintf(out, ":%u", loc.line); if (loc.column != 0) ir_fprintf(out, ":%u", loc.column); } fputc(')', out); } fputs(": ", out); } ir_fprintf(out, "%s: ", kind); ir_vfprintf(out, fmt, ap); fputc('\n', out); }
static void replace_with_call(ir_node *node) { widen_builtin(node); ir_type *const mtp = get_Builtin_type(node); ir_builtin_kind const kind = get_Builtin_kind(node); char const *const name = get_builtin_name(kind); ir_type *const arg1 = get_method_param_type(mtp, 0); char const *const machmode = get_gcc_machmode(arg1); ident *const id = new_id_fmt("__%s%s2", name, machmode); ir_entity *const entity = create_compilerlib_entity(get_id_str(id), mtp); dbg_info *const dbgi = get_irn_dbg_info(node); ir_node *const block = get_nodes_block(node); ir_node *const mem = get_Builtin_mem(node); ir_graph *const irg = get_irn_irg(node); ir_node *const callee = new_r_Address(irg, entity); int const n_params = get_Builtin_n_params(node); ir_node **const params = get_Builtin_param_arr(node); ir_node *const call = new_rd_Call(dbgi, block, mem, callee, n_params, params, mtp); ir_node *const call_mem = new_r_Proj(call, mode_M, pn_Call_M); ir_node *const call_ress = new_r_Proj(call, mode_T, pn_Call_T_result); ir_type *const res_type = get_method_res_type(mtp, 0); ir_mode *const res_mode = get_type_mode(res_type); ir_node *const call_res = new_r_Proj(call_ress, res_mode, 0); ir_node *const in[] = { [pn_Builtin_M] = call_mem, [pn_Builtin_max + 1] = call_res, };
/** * Copies a node to a new irg. The Ins of the new node point to * the predecessors on the old irg. n->link points to the new node. * * @param n The node to be copied * @param irg the new irg * * Does NOT copy standard nodes like Start, End etc that are fixed * in an irg. Instead, the corresponding nodes of the new irg are returned. * Note further, that the new nodes have no block. */ static void copy_irn_to_irg(ir_node *n, ir_graph *irg) { /* do not copy standard nodes */ ir_node *nn = NULL; switch (get_irn_opcode(n)) { case iro_NoMem: nn = get_irg_no_mem(irg); break; case iro_Block: { ir_graph *old_irg = get_irn_irg(n); if (n == get_irg_start_block(old_irg)) nn = get_irg_start_block(irg); else if (n == get_irg_end_block(old_irg)) nn = get_irg_end_block(irg); break; } case iro_Start: nn = get_irg_start(irg); break; case iro_End: nn = get_irg_end(irg); break; case iro_Proj: { ir_graph *old_irg = get_irn_irg(n); if (n == get_irg_frame(old_irg)) nn = get_irg_frame(irg); else if (n == get_irg_initial_mem(old_irg)) nn = get_irg_initial_mem(irg); else if (n == get_irg_args(old_irg)) nn = get_irg_args(irg); break; } } if (nn) { set_irn_link(n, nn); return; } nn = new_ir_node(get_irn_dbg_info(n), irg, NULL, /* no block yet, will be set later */ get_irn_op(n), get_irn_mode(n), get_irn_arity(n), get_irn_in(n)); /* Copy the attributes. These might point to additional data. If this was allocated on the old obstack the pointers now are dangling. This frees e.g. the memory of the graph_arr allocated in new_immBlock. */ copy_node_attr(irg, n, nn); set_irn_link(n, nn); }
/** * Block-walker, remove Bad block predecessors and shorten Phis. * Phi links must be up-to-date. */ static void block_remove_bads(ir_node *block) { /* 1. Create a new block without Bad inputs */ ir_graph *irg = get_irn_irg(block); const int max = get_Block_n_cfgpreds(block); ir_node **new_in = ALLOCAN(ir_node*, max); unsigned new_max = 0; for (int i = 0; i < max; ++i) { ir_node *const block_pred = get_Block_cfgpred(block, i); if (!is_Bad(block_pred)) { new_in[new_max++] = block_pred; } } /* If the end block is unreachable, it might have zero predecessors. */ if (new_max == 0) { ir_node *end_block = get_irg_end_block(irg); if (block == end_block) { set_irn_in(block, new_max, new_in); return; } } dbg_info *dbgi = get_irn_dbg_info(block); ir_node *new_block = new_rd_Block(dbgi, irg, new_max, new_in); ir_entity *block_entity = get_Block_entity(block); set_Block_entity(new_block, block_entity); /* 2. Remove inputs on Phis, where the block input is Bad. */ for (ir_node *phi = get_Block_phis(block), *next; phi != NULL; phi = next) { next = get_Phi_next(phi); assert(get_irn_arity(phi) == max); unsigned j = 0; foreach_irn_in(phi, i, pred) { ir_node *const block_pred = get_Block_cfgpred(block, i); if (!is_Bad(block_pred)) { new_in[j++] = pred; } } assert(j == new_max); /* shortcut if only 1 phi input is left */ if (new_max == 1) { ir_node *new_node = new_in[0]; /* can happen inside unreachable endless loops */ if (new_node == phi) return; if (get_Phi_loop(phi)) remove_keep_alive(phi); exchange(phi, new_node); } else { set_irn_in(phi, new_max, new_in); } }
/** patches Addresses to work in position independent code */ static void fix_pic_addresses(ir_node *const node, void *const data) { (void)data; ir_graph *const irg = get_irn_irg(node); be_main_env_t *const be = be_get_irg_main_env(irg); foreach_irn_in(node, i, pred) { if (!is_Address(pred)) continue; ir_node *res; ir_entity *const entity = get_Address_entity(pred); dbg_info *const dbgi = get_irn_dbg_info(pred); if (i == n_Call_ptr && is_Call(node)) { /* Calls can jump to relative addresses, so we can directly jump to * the (relatively) known call address or the trampoline */ if (can_address_relative(entity)) continue; ir_entity *const trampoline = get_trampoline(be, entity); res = new_rd_Address(dbgi, irg, trampoline); } else if (get_entity_type(entity) == get_code_type()) { /* Block labels can always be addressed directly. */ continue; } else { /* Everything else is accessed relative to EIP. */ ir_node *const block = get_nodes_block(pred); ir_mode *const mode = get_irn_mode(pred); ir_node *const pic_base = ia32_get_pic_base(irg); if (can_address_relative(entity)) { /* All ok now for locally constructed stuff. */ res = new_rd_Add(dbgi, block, pic_base, pred, mode); /* Make sure the walker doesn't visit this add again. */ mark_irn_visited(res); } else { /* Get entry from pic symbol segment. */ ir_entity *const pic_symbol = get_pic_symbol(be, entity); ir_node *const pic_address = new_rd_Address(dbgi, irg, pic_symbol); ir_node *const add = new_rd_Add(dbgi, block, pic_base, pic_address, mode); mark_irn_visited(add); /* We need an extra indirection for global data outside our current * module. The loads are always safe and can therefore float and * need no memory input */ ir_type *const type = get_entity_type(entity); ir_node *const nomem = get_irg_no_mem(irg); ir_node *const load = new_rd_Load(dbgi, block, nomem, add, mode, type, cons_floats); res = new_r_Proj(load, mode, pn_Load_res); } } set_irn_n(node, i, res); } }
/** * lower 64bit addition: an 32bit add for the lower parts, an add with * carry for the higher parts. If the carry's value is known, fold it * into the upper add. */ static void ia32_lower_add64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Add_left(node); ir_node *right = get_Add_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_mode *low_mode = get_irn_mode(left_low); ir_mode *high_mode = get_irn_mode(left_high); carry_result cr = lower_add_carry(left, right, low_mode); assert(get_irn_mode(left_low) == get_irn_mode(right_low)); assert(get_irn_mode(left_high) == get_irn_mode(right_high)); if (cr == no_carry) { ir_node *add_low = new_rd_Add(dbg, block, left_low, right_low, low_mode); ir_node *add_high = new_rd_Add(dbg, block, left_high, right_high, high_mode); ir_set_dw_lowered(node, add_low, add_high); } else if (cr == must_carry && (is_Const(left_high) || is_Const(right_high))) { // We cannot assume that left_high and right_high form a normalized Add. ir_node *constant; ir_node *other; if (is_Const(left_high)) { constant = left_high; other = right_high; } else { constant = right_high; other = left_high; } ir_graph *irg = get_irn_irg(right_high); ir_node *one = new_rd_Const(dbg, irg, get_mode_one(high_mode)); ir_node *const_plus_one = new_rd_Add(dbg, block, constant, one, high_mode); ir_node *add_high = new_rd_Add(dbg, block, other, const_plus_one, high_mode); ir_node *add_low = new_rd_Add(dbg, block, left_low, right_low, low_mode); ir_set_dw_lowered(node, add_low, add_high); } else { /* l_res = a_l + b_l */ ir_node *add_low = new_bd_ia32_l_Add(dbg, block, left_low, right_low); ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode; ir_node *res_low = new_r_Proj(add_low, ia32_mode_gp, pn_ia32_l_Add_res); ir_node *flags = new_r_Proj(add_low, mode_flags, pn_ia32_l_Add_flags); /* h_res = a_h + b_h + carry */ ir_node *add_high = new_bd_ia32_l_Adc(dbg, block, left_high, right_high, flags, mode); ir_set_dw_lowered(node, res_low, add_high); } }
/** * lower 64bit minus operation */ static void ia32_lower_minus64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *op = get_Minus_op(node); ir_node *op_low = get_lowered_low(op); ir_node *op_high = get_lowered_high(op); ir_node *minus = new_bd_ia32_l_Minus64(dbg, block, op_low, op_high); ir_node *l_res = new_r_Proj(minus, ia32_mode_gp, pn_ia32_Minus64_res_low); ir_node *h_res = new_r_Proj(minus, mode, pn_ia32_Minus64_res_high); ir_set_dw_lowered(node, l_res, h_res); }
/** * lower 64bit subtraction: a 32bit sub for the lower parts, a sub * with borrow for the higher parts. If the borrow's value is known, * fold it into the upper sub. */ static void ia32_lower_sub64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Sub_left(node); ir_node *right = get_Sub_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_mode *low_mode = get_irn_mode(left_low); ir_mode *high_mode = get_irn_mode(left_high); carry_result cr = lower_sub_borrow(left, right, low_mode); assert(get_irn_mode(left_low) == get_irn_mode(right_low)); assert(get_irn_mode(left_high) == get_irn_mode(right_high)); if (cr == no_carry) { ir_node *sub_low = new_rd_Sub(dbg, block, left_low, right_low, low_mode); ir_node *sub_high = new_rd_Sub(dbg, block, left_high, right_high, high_mode); ir_set_dw_lowered(node, sub_low, sub_high); } else if (cr == must_carry && (is_Const(left_high) || is_Const(right_high))) { ir_node *sub_high; ir_graph *irg = get_irn_irg(right_high); ir_node *one = new_rd_Const(dbg, irg, get_mode_one(high_mode)); if (is_Const(right_high)) { ir_node *new_const = new_rd_Add(dbg, block, right_high, one, high_mode); sub_high = new_rd_Sub(dbg, block, left_high, new_const, high_mode); } else if (is_Const(left_high)) { ir_node *new_const = new_rd_Sub(dbg, block, left_high, one, high_mode); sub_high = new_rd_Sub(dbg, block, new_const, right_high, high_mode); } else { panic("logic error"); } ir_node *sub_low = new_rd_Sub(dbg, block, left_low, right_low, low_mode); ir_set_dw_lowered(node, sub_low, sub_high); } else { /* l_res = a_l - b_l */ ir_node *sub_low = new_bd_ia32_l_Sub(dbg, block, left_low, right_low); ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode; ir_node *res_low = new_r_Proj(sub_low, ia32_mode_gp, pn_ia32_l_Sub_res); ir_node *flags = new_r_Proj(sub_low, mode_flags, pn_ia32_l_Sub_flags); /* h_res = a_h - b_h - carry */ ir_node *sub_high = new_bd_ia32_l_Sbb(dbg, block, left_high, right_high, flags, mode); ir_set_dw_lowered(node, res_low, sub_high); } }
/** * Transforms a Conv into the appropriate soft float function. */ static bool lower_Conv(ir_node *const n) { dbg_info *const dbgi = get_irn_dbg_info(n); ir_node *const block = get_nodes_block(n); ir_mode *const mode = get_irn_mode(n); ir_node *op = get_Conv_op(n); ir_mode *op_mode = get_irn_mode(op); char const *name; if (!mode_is_float(mode)) { if (!mode_is_float(op_mode)) return false; if (mode_is_signed(mode)) name = "fix"; else name = "fixuns"; } else if (!mode_is_float(op_mode)) { ir_mode *min_mode; if (mode_is_signed(op_mode)) { name = "float"; min_mode = mode_Is; } else { name = "floatun"; min_mode = mode_Iu; } if (get_mode_size_bits(op_mode) < get_mode_size_bits(min_mode)) { op_mode = min_mode; op = new_rd_Conv(dbgi, block, op, op_mode); } } else { /* Remove unnecessary Convs. */ if (op_mode == mode) { exchange(n, op); return true; } if (get_mode_size_bits(op_mode) > get_mode_size_bits(mode)) name = "trunc"; else name = "extend"; } ir_node *const in[] = { op }; ir_node *result = make_softfloat_call(n, name, ARRAY_SIZE(in), in); /* Check whether we need a Conv for the result. */ if (get_irn_mode(result) != mode) result = new_rd_Conv(dbgi, block, result, mode); exchange(n, result); return true; }
void be_emit_finish_line_gas(const ir_node *node) { if (node && be_options.verbose_asm) { be_emit_pad_comment(); dbg_info *const dbg = get_irn_dbg_info(node); src_loc_t const loc = ir_retrieve_dbg_info(dbg); char const *const fmt = !loc.file ? "/* %+F */\n" : loc.line == 0 ? "/* %+F %s */\n" : loc.column == 0 ? "/* %+F %s:%u */\n" : /* */ "/* %+F %s:%u:%u */\n"; be_emit_irprintf(fmt, node, loc.file, loc.line, loc.column); } else { be_emit_char('\n'); } be_emit_write_line(); }
static ir_node *make_softfloat_call(ir_node *const n, char const *const name, size_t const arity, ir_node *const *const in) { dbg_info *const dbgi = get_irn_dbg_info(n); ir_node *const block = get_nodes_block(n); ir_graph *const irg = get_irn_irg(n); ir_node *const nomem = get_irg_no_mem(irg); ir_node *const callee = create_softfloat_address(n, name); ir_type *const type = get_softfloat_type(n); ir_mode *const res_mode = get_type_mode(get_method_res_type(type, 0)); ir_node *const call = new_rd_Call(dbgi, block, nomem, callee, arity, in, type); ir_node *const results = new_r_Proj(call, mode_T, pn_Call_T_result); ir_node *const result = new_r_Proj(results, res_mode, 0); return result; }
static void lower64_add(ir_node *node, ir_mode *mode) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Add_left(node); ir_node *right = get_Add_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_node *adds = new_bd_arm_AddS_t(dbgi, block, left_low, right_low); ir_mode *mode_low = get_irn_mode(left_low); ir_node *res_low = new_r_Proj(adds, mode_low, pn_arm_AddS_t_res); ir_node *res_flags = new_r_Proj(adds, mode_ANY, pn_arm_AddS_t_flags); ir_node *adc = new_bd_arm_AdC_t(dbgi, block, left_high, right_high, res_flags, mode); ir_set_dw_lowered(node, res_low, adc); }
static void lower64_sub(ir_node *node, ir_mode *mode) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Sub_left(node); ir_node *right = get_Sub_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_node *subs = new_bd_arm_SubS_t(dbgi, block, left_low, right_low); ir_mode *mode_low = get_irn_mode(left_low); ir_node *res_low = new_r_Proj(subs, mode_low, pn_arm_SubS_t_res); ir_node *res_flags = new_r_Proj(subs, mode_ANY, pn_arm_SubS_t_flags); ir_node *sbc = new_bd_arm_SbC_t(dbgi, block, left_high, right_high, res_flags, mode); ir_set_dw_lowered(node, res_low, sbc); }
/** * lower Alloca nodes to allocate "bytes" instead of a certain type */ static void lower_node(ir_node *node, void *data) { bool *changed = (bool*)data; if (!is_Alloc(node)) return; ir_node *const size = get_Alloc_size(node); ir_node *const mem = get_Alloc_mem(node); ir_node *const block = get_nodes_block(node); dbg_info *const dbgi = get_irn_dbg_info(node); ir_node *const new_size = adjust_alloc_size(dbgi, size, block); ir_node *const new_node = new_rd_Alloc(dbgi, block, mem, new_size, 1); if (new_node != node) exchange(node, new_node); *changed = true; }
/** * Turn a small CopyB node into a series of Load/Store nodes. */ static void lower_small_copyb_node(ir_node *irn) { ir_graph *irg = get_irn_irg(irn); dbg_info *dbgi = get_irn_dbg_info(irn); ir_node *block = get_nodes_block(irn); ir_type *tp = get_CopyB_type(irn); ir_node *addr_src = get_CopyB_src(irn); ir_node *addr_dst = get_CopyB_dst(irn); ir_node *mem = get_CopyB_mem(irn); ir_mode *mode_ref = get_irn_mode(addr_src); unsigned mode_bytes = allow_misalignments ? native_mode_bytes : get_type_alignment(tp); unsigned size = get_type_size(tp); unsigned offset = 0; bool is_volatile = get_CopyB_volatility(irn) == volatility_is_volatile; ir_cons_flags flags = is_volatile ? cons_volatile : cons_none; while (offset < size) { ir_mode *mode = get_ir_mode(mode_bytes); for (; offset + mode_bytes <= size; offset += mode_bytes) { ir_mode *mode_ref_int = get_reference_offset_mode(mode_ref); /* construct offset */ ir_node *addr_const = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add = new_r_Add(block, addr_src, addr_const); ir_node *load = new_rd_Load(dbgi, block, mem, add, mode, tp, flags); ir_node *load_res = new_r_Proj(load, mode, pn_Load_res); ir_node *load_mem = new_r_Proj(load, mode_M, pn_Load_M); ir_node *addr_const2 = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add2 = new_r_Add(block, addr_dst, addr_const2); ir_node *store = new_rd_Store(dbgi, block, load_mem, add2, load_res, tp, flags); ir_node *store_mem = new_r_Proj(store, mode_M, pn_Store_M); mem = store_mem; } mode_bytes /= 2; } exchange(irn, mem); }
/** * lower 64bit Mul operation. */ static void ia32_lower_mul64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Mul_left(node); ir_node *right = get_Mul_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); /* EDX:EAX = left_low * right_low l_res = EAX t1 = right_low * left_high t2 = t1 + EDX t3 = left_low * right_high h_res = t2 + t3 */ /* handle the often used case of 32x32=64 mul */ ir_node *h_res; ir_node *l_res; if (is_sign_extend(left_low, left_high) && is_sign_extend(right_low, right_high)) { ir_node *mul = new_bd_ia32_l_IMul(dbg, block, left_low, right_low); h_res = new_rd_Proj(dbg, mul, mode, pn_ia32_l_IMul_res_high); l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_IMul_res_low); } else { /* note that zero extension is handled hare efficiently */ ir_node *mul = new_bd_ia32_l_Mul(dbg, block, left_low, right_low); ir_node *pEDX = new_rd_Proj(dbg, mul, mode, pn_ia32_l_Mul_res_high); l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_Mul_res_low); ir_node *right_lowc = new_rd_Conv(dbg, block, right_low, mode); ir_node *mul1 = new_rd_Mul(dbg, block, left_high, right_lowc, mode); ir_node *add = new_rd_Add(dbg, block, mul1, pEDX, mode); ir_node *left_lowc = new_rd_Conv(dbg, block, left_low, mode); ir_node *mul2 = new_rd_Mul(dbg, block, left_lowc, right_high, mode); h_res = new_rd_Add(dbg, block, add, mul2, mode); } ir_set_dw_lowered(node, l_res, h_res); }
/** * Transform helper for blocks. */ static ir_node *transform_block(ir_node *node) { ir_graph *irg = get_irn_irg(node); dbg_info *dbgi = get_irn_dbg_info(node); ir_mode *mode = get_irn_mode(node); ir_node *block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), mode, get_irn_arity(node), get_irn_in(node) + 1); copy_node_attr(irg, node, block); block->node_nr = node->node_nr; /* transfer execfreq value */ double execfreq = get_block_execfreq(node); set_block_execfreq(block, execfreq); /* put the preds in the worklist */ be_enqueue_preds(node); return block; }
static void lower64_minus(ir_node *node, ir_mode *mode) { dbg_info *dbgi = get_irn_dbg_info(node); ir_graph *irg = get_irn_irg(node); ir_node *block = get_nodes_block(node); ir_node *op = get_Minus_op(node); ir_node *right_low = get_lowered_low(op); ir_node *right_high = get_lowered_high(op); ir_mode *low_unsigned = get_irn_mode(right_low); ir_node *left_low = new_r_Const_null(irg, low_unsigned); ir_node *left_high = new_r_Const_null(irg, mode); ir_node *subs = new_bd_arm_SubS_t(dbgi, block, left_low, right_low); ir_node *res_low = new_r_Proj(subs, low_unsigned, pn_arm_SubS_t_res); ir_node *res_flags = new_r_Proj(subs, mode_ANY, pn_arm_SubS_t_flags); ir_node *sbc = new_bd_arm_SbC_t(dbgi, block, left_high, right_high, res_flags, mode); ir_set_dw_lowered(node, res_low, sbc); }
static bool lower_Bitcast(ir_node *const n) { /* bitcast was casting float->int or int->float we can simply replace it * with a conv (between integer modes) now. */ ir_node *op = get_Bitcast_op(n); ir_mode *src_mode = get_irn_mode(op); ir_mode *dst_mode = get_irn_mode(n); /* note that the predecessor may already be transformed, so it's * possible that we don't see a float mode anymore. */ if (mode_is_float(dst_mode)) dst_mode = get_lowered_mode(dst_mode); ir_node *res = op; if (src_mode != dst_mode) { dbg_info *dbgi = get_irn_dbg_info(n); ir_node *block = get_nodes_block(n); res = new_rd_Conv(dbgi, block, op, dst_mode); } exchange(n, res); return true; }
/** * Turn a large CopyB node into a memcpy call. */ static void lower_large_copyb_node(ir_node *irn) { ir_graph *irg = get_irn_irg(irn); ir_node *block = get_nodes_block(irn); dbg_info *dbgi = get_irn_dbg_info(irn); ir_node *mem = get_CopyB_mem(irn); ir_node *addr_src = get_CopyB_src(irn); ir_node *addr_dst = get_CopyB_dst(irn); ir_type *copyb_tp = get_CopyB_type(irn); unsigned size = get_type_size(copyb_tp); ir_node *callee = get_memcpy_address(irg); ir_type *call_tp = get_memcpy_methodtype(); ir_mode *mode_size_t = get_ir_mode(native_mode_bytes); ir_node *size_cnst = new_r_Const_long(irg, mode_size_t, size); ir_node *in[] = { addr_dst, addr_src, size_cnst }; ir_node *call = new_rd_Call(dbgi, block, mem, callee, ARRAY_SIZE(in), in, call_tp); ir_node *call_mem = new_r_Proj(call, mode_M, pn_Call_M); exchange(irn, call_mem); }
/** * Transforms a Sub to a Neg + Add, which subsequently allows swapping * of the inputs. The swapping is also (implicitly) done here. */ static void transform_sub_to_neg_add(ir_node *node, const arch_register_t *out_reg) { ir_node *block = get_nodes_block(node); dbg_info *dbgi = get_irn_dbg_info(node); ir_node *in1 = get_irn_n(node, 0); ir_node *in2 = get_irn_n(node, 1); const arch_register_t *in2_reg = arch_get_irn_register(in2); const amd64_binop_addr_attr_t *attr = get_amd64_binop_addr_attr(node); ir_node *add; unsigned pos; if (is_amd64_subs(node)) { unsigned bits = x86_bytes_from_size(attr->base.base.size) * 8; ir_tarval *tv = get_mode_one(amd64_mode_xmm); tv = tarval_shl_unsigned(tv, bits - 1); ir_entity *sign_bit_const = create_float_const_entity(tv); amd64_binop_addr_attr_t xor_attr = { .base = { .base = { .op_mode = AMD64_OP_REG_ADDR, .size = X86_SIZE_64, }, }, }; init_lconst_addr(&xor_attr.base.addr, sign_bit_const); ir_node *xor_in[] = { in2 }; ir_node *const xor = new_bd_amd64_xorp(dbgi, block, ARRAY_SIZE(xor_in), xor_in, amd64_xmm_reqs, &xor_attr); sched_add_before(node, xor); ir_node *const neg = be_new_Proj_reg(xor, pn_amd64_xorp_res, in2_reg); ir_node *in[] = { neg, in1 }; add = new_bd_amd64_adds(dbgi, block, ARRAY_SIZE(in), in, amd64_xmm_xmm_reqs, attr); pos = pn_amd64_adds_res; } else {
void be_default_lower_va_arg(ir_node *const node, bool const compound_is_ptr, unsigned const stack_param_align) { ir_node *block = get_nodes_block(node); dbg_info *dbgi = get_irn_dbg_info(node); ir_graph *irg = get_irn_irg(node); ir_type *aptype = get_method_res_type(get_Builtin_type(node), 0); ir_node *const ap = get_irn_n(node, 1); ir_node *const node_mem = get_Builtin_mem(node); ir_mode *apmode = get_type_mode(aptype); ir_node *res; ir_node *new_mem; if (apmode) { goto load; } else if (compound_is_ptr) { apmode = mode_P; aptype = get_type_for_mode(apmode); load:; ir_node *const load = new_rd_Load(dbgi, block, node_mem, ap, apmode, aptype, cons_none); res = new_r_Proj(load, apmode, pn_Load_res); new_mem = new_r_Proj(load, mode_M,pn_Load_M); } else { /* aptype has no associated mode, so it is represented as a pointer. */ res = ap; new_mem = node_mem; } unsigned const round_up = round_up2(get_type_size(aptype), stack_param_align); ir_mode *const offset_mode = get_reference_offset_mode(mode_P); ir_node *const offset = new_r_Const_long(irg, offset_mode, round_up); ir_node *const new_ap = new_rd_Add(dbgi, block, ap, offset); ir_node *const in[] = { new_mem, res, new_ap }; turn_into_tuple(node, ARRAY_SIZE(in), in); }
/* * Transform Sel[method] to SymC[method] if possible. * (see opt_polymorphy in libfirm) */ static ir_node *transform_node_Sel2(ir_node *node) { ir_node *new_node; ir_entity *ent = get_Sel_entity(node); if (get_irp_phase_state() == phase_building) return node; if (!get_opt_dyn_meth_dispatch()) return node; if (!is_Method_type(get_entity_type(ent))) return node; ddispatch_binding bind = oo_get_entity_binding(ent); assert (bind != bind_unknown); if (bind == bind_static) return node; /* If we know the dynamic type, we can replace the Sel by a constant. */ ir_node *ptr = get_Sel_ptr(node); /* The address we select from. */ ir_type *dyn_tp = get_irn_typeinfo_type(ptr); if (dyn_tp != initial_type) { ir_entity *called_ent; /* We know which method will be called, no dispatch necessary. */ called_ent = resolve_ent_polymorphy(dyn_tp, ent); assert (! oo_get_method_is_abstract(called_ent)); assert (! oo_get_class_is_interface(get_entity_owner(called_ent))); new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(called_ent), get_nodes_block(node)); return new_node; } return node; }
static void transform_Proj_Alloc(ir_node *node) { /* we might need a result adjustment */ if (addr_delta == 0) return; if (get_Proj_proj(node) != pn_Alloc_res) return; if (ir_nodeset_contains(&transformed, node)) return; ir_node *const alloc = get_Proj_pred(node); dbg_info *const dbgi = get_irn_dbg_info(alloc); ir_graph *const irg = get_irn_irg(node); ir_node *const block = get_nodes_block(node); ir_node *const delta = new_r_Const_long(irg, mode_P, addr_delta); ir_node *const dummy = new_r_Dummy(irg, mode_P); ir_node *const add = new_rd_Add(dbgi, block, dummy, delta, mode_P); exchange(node, add); ir_node *const new_proj = new_r_Proj(alloc, mode_P, pn_Alloc_res); set_Add_left(add, new_proj); ir_nodeset_insert(&transformed, new_proj); }