From: Christoph Mallon Date: Wed, 8 Oct 2008 14:06:58 +0000 (+0000) Subject: Introduce ia32_Call, which can handle address mode. X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=fd07b1498438629b4ef81343573377e3e535048f;p=libfirm Introduce ia32_Call, which can handle address mode. [r22609] --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 7fc5d809f..3e6a1f077 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -392,6 +392,9 @@ static void ia32_set_frame_offset(ir_node *irn, int bias) static int ia32_get_sp_bias(const ir_node *node) { + if (is_ia32_Call(node)) + return -(int)get_ia32_call_attr_const(node)->pop; + if (is_ia32_Push(node)) return 4; @@ -1889,7 +1892,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, call_flags.bits.store_args_sequential = 0; /* call_flags.bits.try_omit_fp not changed: can handle both settings */ call_flags.bits.fp_free = 0; /* the frame pointer is fixed in IA32 */ - call_flags.bits.call_has_imm = 1; /* No call immediates, we handle this by ourselves */ + call_flags.bits.call_has_imm = 0; /* No call immediates, we handle this by ourselves */ /* set parameter passing style */ be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks); @@ -2088,16 +2091,13 @@ static const be_execution_unit_t ***ia32_get_allowed_execution_units( if (is_ia32_irn(irn)) { ret = get_ia32_exec_units(irn); - } - else if (is_be_node(irn)) { - if (be_is_Call(irn) || be_is_Return(irn)) { + } else if (is_be_node(irn)) { + if (be_is_Return(irn)) { ret = _units_callret; - } - else if (be_is_Barrier(irn)) { + } else if (be_is_Barrier(irn)) { ret = _units_dummy; - } - else { - ret = _units_other; + } else { + ret = _units_other; } } else { diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 7061a7c46..babfd970a 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -255,7 +255,52 @@ void ia32_emit_source_register(const ir_node *node, int pos) emit_register(reg, NULL); } -static void emit_ia32_Immediate(const ir_node *node); +static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust) +{ + ident *id; + + set_entity_backend_marked(entity, 1); + id = get_entity_ld_ident(entity); + be_emit_ident(id); + + if (get_entity_owner(entity) == get_tls_type()) { + if (get_entity_visibility(entity) == visibility_external_allocated) { + be_emit_cstring("@INDNTPOFF"); + } else { + be_emit_cstring("@NTPOFF"); + } + } + + if (!no_pic_adjust && do_pic) { + /* TODO: only do this when necessary */ + be_emit_char('-'); + be_emit_string(pic_base_label); + } +} + +static void emit_ia32_Immediate_no_prefix(const ir_node *node) +{ + const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node); + + if (attr->symconst != NULL) { + if (attr->sc_sign) + be_emit_char('-'); + ia32_emit_entity(attr->symconst, 0); + } + if (attr->symconst == NULL || attr->offset != 0) { + if (attr->symconst != NULL) { + be_emit_irprintf("%+d", attr->offset); + } else { + be_emit_irprintf("0x%X", attr->offset); + } + } +} + +static void emit_ia32_Immediate(const ir_node *node) +{ + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(node); +} void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos) { @@ -476,6 +521,11 @@ static void ia32_emit_cmp_suffix(int pnc) be_emit_string(str); } +typedef enum ia32_emit_mod_t { + EMIT_RESPECT_LS = 1U << 0, + EMIT_ALTERNATE_AM = 1U << 1 +} ia32_emit_mod_t; + /** * fmt parameter output * ---- ---------------------- --------------------------------------------- @@ -495,6 +545,7 @@ static void ia32_emit_cmp_suffix(int pnc) * * x starts at 0 * # modifier for %ASx, %D and %S uses ls mode of node to alter register width + * * modifier does not prefix immediates with $, but AM with * */ static void ia32_emitf(const ir_node *node, const char *fmt, ...) { @@ -502,8 +553,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) va_start(ap, fmt); for (;;) { - const char *start = fmt; - const ir_mode *mode = NULL; + const char *start = fmt; + ia32_emit_mod_t mod = 0; while (*fmt != '%' && *fmt != '\n' && *fmt != '\0') ++fmt; @@ -523,8 +574,13 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) break; ++fmt; + if (*fmt == '*') { + mod |= EMIT_ALTERNATE_AM; + ++fmt; + } + if (*fmt == '#') { - mode = get_ia32_ls_mode(node); + mod |= EMIT_RESPECT_LS; ++fmt; } @@ -536,12 +592,16 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) case 'A': { switch (*fmt++) { case 'M': + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); ia32_emit_am(node); break; case 'R': { const arch_register_t *reg = va_arg(ap, const arch_register_t*); if (get_ia32_op_type(node) == ia32_AddrModeS) { + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); ia32_emit_am(node); } else { emit_register(reg, NULL); @@ -551,6 +611,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) case 'S': if (get_ia32_op_type(node) == ia32_AddrModeS) { + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); ia32_emit_am(node); ++fmt; } else { @@ -573,12 +635,14 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) pos = *fmt++ - '0'; reg = get_out_reg(node, pos); - emit_register(reg, mode); + emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL); break; } case 'I': - emit_ia32_Immediate(node); + if (!(mod & EMIT_ALTERNATE_AM)) + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(node); break; case 'L': @@ -613,10 +677,12 @@ emit_S: pos = *fmt++ - '0'; in = get_irn_n(node, pos); if (is_ia32_Immediate(in)) { - emit_ia32_Immediate(in); + if (!(mod & EMIT_ALTERNATE_AM)) + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(in); } else { const arch_register_t *reg = get_in_reg(node, pos); - emit_register(reg, mode); + emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL); } break; } @@ -698,29 +764,6 @@ void ia32_emit_unop(const ir_node *node, int pos) ia32_emitf(node, fmt); } -static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust) -{ - ident *id; - - set_entity_backend_marked(entity, 1); - id = get_entity_ld_ident(entity); - be_emit_ident(id); - - if (get_entity_owner(entity) == get_tls_type()) { - if (get_entity_visibility(entity) == visibility_external_allocated) { - be_emit_cstring("@INDNTPOFF"); - } else { - be_emit_cstring("@NTPOFF"); - } - } - - if (!no_pic_adjust && do_pic) { - /* TODO: only do this when necessary */ - be_emit_char('-'); - be_emit_string(pic_base_label); - } -} - /** * Emits address mode. */ @@ -1215,25 +1258,6 @@ static void emit_Jmp(const ir_node *node) } } -static void emit_ia32_Immediate(const ir_node *node) -{ - const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node); - - be_emit_char('$'); - if (attr->symconst != NULL) { - if (attr->sc_sign) - be_emit_char('-'); - ia32_emit_entity(attr->symconst, 0); - } - if (attr->symconst == NULL || attr->offset != 0) { - if (attr->symconst != NULL) { - be_emit_irprintf("%+d", attr->offset); - } else { - be_emit_irprintf("0x%X", attr->offset); - } - } -} - /** * Emit an inline assembler operand. * @@ -1521,6 +1545,16 @@ static void emit_ia32_Conv_I2I(const ir_node *node) } } +/** + * Emits a call + */ +static void emit_ia32_Call(const ir_node *node) +{ + /* Special case: Call must not have its immediates prefixed by $, instead + * address mode is prefixed by *. */ + ia32_emitf(node, "\tcall %*AS3\n"); +} + /******************************************* * _ _ @@ -1532,24 +1566,6 @@ static void emit_ia32_Conv_I2I(const ir_node *node) * *******************************************/ -/** - * Emits a backend call - */ -static void emit_be_Call(const ir_node *node) -{ - ir_entity *ent = be_Call_get_entity(node); - - be_emit_cstring("\tcall "); - if (ent) { - ia32_emit_entity(ent, 1); - } else { - const arch_register_t *reg = get_in_reg(node, be_pos_Call_ptr); - be_emit_char('*'); - emit_register(reg, NULL); - } - be_emit_finish_line_gas(node); -} - /** * Emits code to increase stack pointer. */ @@ -1795,6 +1811,7 @@ static void ia32_register_emitters(void) IA32_EMIT2(Conv_I2I8Bit, Conv_I2I); IA32_EMIT(Asm); IA32_EMIT(CMov); + IA32_EMIT(Call); IA32_EMIT(Const); IA32_EMIT(Conv_FP2FP); IA32_EMIT(Conv_FP2I); @@ -1810,7 +1827,6 @@ static void ia32_register_emitters(void) IA32_EMIT(SwitchJmp); /* benode emitter */ - BE_EMIT(Call); BE_EMIT(Copy); BE_EMIT(CopyKeep); BE_EMIT(IncSP); diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index 41bf6f9db..7ff8c49b5 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -438,6 +438,22 @@ const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node) { return cc_attr; } +ia32_call_attr_t *get_ia32_call_attr(ir_node *node) +{ + ia32_attr_t *attr = get_ia32_attr(node); + ia32_call_attr_t *call_attr = CAST_IA32_ATTR(ia32_call_attr_t, attr); + + return call_attr; +} + +const ia32_call_attr_t *get_ia32_call_attr_const(const ir_node *node) +{ + const ia32_attr_t *attr = get_ia32_attr_const(node); + const ia32_call_attr_t *call_attr = CONST_CAST_IA32_ATTR(ia32_call_attr_t, attr); + + return call_attr; +} + ia32_copyb_attr_t *get_ia32_copyb_attr(ir_node *node) { ia32_attr_t *attr = get_ia32_attr(node); ia32_copyb_attr_t *copyb_attr = CAST_IA32_ATTR(ia32_copyb_attr_t, attr); @@ -1095,6 +1111,17 @@ init_ia32_immediate_attributes(ir_node *res, ir_entity *symconst, attr->offset = offset; } +void init_ia32_call_attributes(ir_node *const res, unsigned const pop, ir_type *const call_tp) +{ + ia32_call_attr_t *attr = get_irn_generic_attr(res); + +#ifndef NDEBUG + attr->attr.attr_type |= IA32_ATTR_ia32_call_attr_t; +#endif + attr->pop = pop; + attr->call_tp = call_tp; +} + void init_ia32_copyb_attributes(ir_node *res, unsigned size) { ia32_copyb_attr_t *attr = get_irn_generic_attr(res); @@ -1203,6 +1230,26 @@ int ia32_compare_condcode_attr(ir_node *a, ir_node *b) return 0; } +static int ia32_compare_call_attr(ir_node *a, ir_node *b) +{ + const ia32_call_attr_t *attr_a; + const ia32_call_attr_t *attr_b; + + if (ia32_compare_nodes_attr(a, b)) + return 1; + + attr_a = get_ia32_call_attr_const(a); + attr_b = get_ia32_call_attr_const(b); + + if (attr_a->pop != attr_b->pop) + return 1; + + if (attr_a->call_tp != attr_b->call_tp) + return 1; + + return 0; +} + /** Compare node attributes for CopyB nodes. */ static int ia32_compare_copyb_attr(ir_node *a, ir_node *b) diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index 005577556..56fc5ac57 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -86,6 +86,12 @@ const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node); ia32_condcode_attr_t *get_ia32_condcode_attr(ir_node *node); const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node); +/** + * Gets the Call node attributes. + */ +ia32_call_attr_t *get_ia32_call_attr(ir_node *node); +const ia32_call_attr_t *get_ia32_call_attr_const(const ir_node *node); + /** * Gets the CopyB node attributes. */ @@ -454,6 +460,7 @@ void init_ia32_x87_attributes(ir_node *node); void init_ia32_asm_attributes(ir_node *node); void init_ia32_immediate_attributes(ir_node *node, ir_entity *symconst, int symconst_sign, long offset); +void init_ia32_call_attributes(ir_node *res, unsigned pop, ir_type *call_tp); void init_ia32_copyb_attributes(ir_node *res, unsigned size); void init_ia32_condcode_attributes(ir_node *res, long pnc); diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 2f483d11a..b12a2008f 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -82,7 +82,8 @@ typedef enum { IA32_ATTR_ia32_asm_attr_t = 1 << 2, IA32_ATTR_ia32_immediate_attr_t = 1 << 3, IA32_ATTR_ia32_condcode_attr_t = 1 << 4, - IA32_ATTR_ia32_copyb_attr_t = 1 << 5 + IA32_ATTR_ia32_copyb_attr_t = 1 << 5, + IA32_ATTR_ia32_call_attr_t = 1 << 6 } ia32_attr_type_t; #endif @@ -141,6 +142,16 @@ struct ia32_attr_t { }; COMPILETIME_ASSERT(sizeof(struct ia32_attr_data_bitfield) <= 4, attr_bitfield); +/** + * The attributes for a Call node. + */ +typedef struct ia32_call_attr_t ia32_call_attr_t; +struct ia32_call_attr_t { + ia32_attr_t attr; /**< generic attribute */ + unsigned pop; /**< number of bytes that get popped by the callee */ + ir_type *call_tp; /**< The call type, copied from the original Call node. */ +}; + /** * The attributes for nodes with condition code. */ @@ -204,6 +215,7 @@ struct ia32_asm_attr_t { * the structs (we use them to simulate OO-inheritance) */ union allow_casts_attr_t_ { ia32_attr_t attr; + ia32_call_attr_t call_attr; ia32_condcode_attr_t cc_attr; ia32_copyb_attr_t cpy_attr; ia32_x87_attr_t x87_attr; diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 1f34df034..4bbb018ad 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -279,6 +279,9 @@ $custom_init_attr_func = \&ia32_custom_init_attr; "\tinit_ia32_asm_attributes(res);", ia32_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);", + ia32_call_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". + "\tinit_ia32_call_attributes(res, pop, call_tp);", ia32_condcode_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". "\tinit_ia32_condcode_attributes(res, pnc);", @@ -296,6 +299,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr; %compare_attr = ( ia32_asm_attr_t => "ia32_compare_asm_attr", ia32_attr_t => "ia32_compare_nodes_attr", + ia32_call_attr_t => "ia32_compare_call_attr", ia32_condcode_attr_t => "ia32_compare_condcode_attr", ia32_copyb_attr_t => "ia32_compare_copyb_attr", ia32_immediate_attr_t => "ia32_compare_immediate_attr", @@ -1460,6 +1464,21 @@ Bt => { modified_flags => $status_flags # only CF is set, but the other flags are undefined }, +Call => { + state => "exc_pinned", + reg_req => { + in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ], + out => [ "esp", "fpcw", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ] + }, + ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ], + outs => [ "stack:I|S", "fpcw:I", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ], + attr_type => "ia32_call_attr_t", + attr => "unsigned pop, ir_type *call_tp", + am => "source,unary", + units => [ "BRANCH" ], + latency => 4, # random number +}, + #-----------------------------------------------------------------------------# # _____ _____ ______ __ _ _ _ # # / ____/ ____| ____| / _| | | | | | # diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index cd0ee9cf6..36a031d33 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -4210,14 +4210,30 @@ static ir_node *gen_Proj_Quot(ir_node *node) { panic("No idea how to transform proj->Quot"); } -static ir_node *gen_be_Call(ir_node *node) { - ir_node *res = be_duplicate_node(node); - ir_type *call_tp; - - be_node_add_flags(res, -1, arch_irn_flags_modify_flags); +static ir_node *gen_be_Call(ir_node *node) +{ + dbg_info *const dbgi = get_irn_dbg_info(node); + ir_graph *const irg = current_ir_graph; + ir_node *const src_block = get_nodes_block(node); + ir_node *const block = be_transform_node(src_block); + ir_node *const src_mem = get_irn_n(node, be_pos_Call_mem); + ir_node *const src_sp = get_irn_n(node, be_pos_Call_sp); + ir_node *const sp = be_transform_node(src_sp); + ir_node *const src_ptr = get_irn_n(node, be_pos_Call_ptr); + ir_node *const noreg = ia32_new_NoReg_gp(env_cg); + ia32_address_mode_t am; + ia32_address_t *const addr = &am.addr; + ir_node * mem; + ir_node * call; + int i; + ir_node * fpcw; + ir_node * eax = noreg; + ir_node * ecx = noreg; + ir_node * edx = noreg; + unsigned const pop = be_Call_get_pop(node); + ir_type *const call_tp = be_Call_get_type(node); /* Run the x87 simulator if the call returns a float value */ - call_tp = be_Call_get_type(node); if (get_method_n_ress(call_tp) > 0) { ir_type *const res_type = get_method_res_type(call_tp, 0); ir_mode *const res_mode = get_type_mode(res_type); @@ -4227,7 +4243,41 @@ static ir_node *gen_be_Call(ir_node *node) { } } - return res; + /* We do not want be_Call direct calls */ + assert(be_Call_get_entity(node) == NULL); + + match_arguments(&am, src_block, NULL, src_ptr, src_mem, + match_am | match_immediate); + + i = get_irn_arity(node) - 1; + fpcw = be_transform_node(get_irn_n(node, i--)); + for (; i >= be_pos_Call_first_arg; --i) { + arch_register_req_t const *const req = + arch_get_register_req(env_cg->arch_env, node, i); + ir_node *const reg_parm = be_transform_node(get_irn_n(node, i)); + + assert(req->type == arch_register_req_type_limited); + assert(req->cls == &ia32_reg_classes[CLASS_ia32_gp]); + + switch (*req->limited) { + case 1 << REG_EAX: assert(eax == noreg); eax = reg_parm; break; + case 1 << REG_ECX: assert(ecx == noreg); ecx = reg_parm; break; + case 1 << REG_EDX: assert(edx == noreg); edx = reg_parm; break; + default: panic("Invalid GP register for register parameter"); + } + } + + mem = transform_AM_mem(irg, block, src_ptr, src_mem, addr->mem); + call = new_rd_ia32_Call(dbgi, irg, block, addr->base, addr->index, mem, + am.new_op2, sp, fpcw, eax, ecx, edx, pop, call_tp); + set_am_attributes(call, &am); + call = fix_mem_proj(call, &am); + + if (get_irn_pinned(node) == op_pin_state_pinned) + set_irn_pinned(call, op_pin_state_pinned); + + SET_IA32_ORIG_NODE(call, ia32_get_old_node_name(env_cg, node)); + return call; } static ir_node *gen_be_IncSP(ir_node *node) { @@ -4240,7 +4290,8 @@ static ir_node *gen_be_IncSP(ir_node *node) { /** * Transform the Projs from a be_Call. */ -static ir_node *gen_Proj_be_Call(ir_node *node) { +static ir_node *gen_Proj_be_Call(ir_node *node) +{ ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *call = get_Proj_pred(node); ir_node *new_call = be_transform_node(call); @@ -4252,6 +4303,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { ir_mode *mode = get_irn_mode(node); ir_node *sse_load; const arch_register_class_t *cls; + ir_node *res; /* The following is kinda tricky: If we're using SSE, then we have to * move the result value of the call in floating point registers to an @@ -4270,9 +4322,9 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { call_res_pred = get_Proj_pred(call_res_new); } - if (call_res_pred == NULL || be_is_Call(call_res_pred)) { + if (call_res_pred == NULL || is_ia32_Call(call_res_pred)) { return new_rd_Proj(dbgi, irg, block, new_call, mode_M, - pn_be_Call_M_regular); + n_ia32_Call_mem); } else { assert(is_ia32_xLoad(call_res_pred)); return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M, @@ -4319,7 +4371,47 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { mode = cls->mode; } - return new_rd_Proj(dbgi, irg, block, new_call, mode, proj); + /* Map from be_Call to ia32_Call proj number */ + if (proj == pn_be_Call_sp) { + proj = pn_ia32_Call_stack; + } else if (proj == pn_be_Call_M_regular) { + proj = pn_ia32_Call_M; + } else { + arch_register_req_t const *const req = arch_get_register_req(env_cg->arch_env, node, BE_OUT_POS(proj)); + int const n_outs = get_ia32_n_res(new_call); + int i; + + assert(proj >= pn_be_Call_first_res); + assert(req->type == arch_register_req_type_limited); + + for (i = 0; i < n_outs; ++i) { + arch_register_req_t const *const new_req = get_ia32_out_req(new_call, i); + + if (new_req->type != arch_register_req_type_limited || + new_req->cls != req->cls || + *new_req->limited != *req->limited) + continue; + + proj = i; + break; + } + assert(i < n_outs); + } + + res = new_rd_Proj(dbgi, irg, block, new_call, mode, proj); + + /* TODO arch_set_irn_register() only operates on Projs, need variant with index */ + switch (proj) { + case pn_ia32_Call_stack: + arch_set_irn_register(env_cg->arch_env, res, &ia32_gp_regs[REG_ESP]); + break; + + case pn_ia32_Call_fpcw: + arch_set_irn_register(env_cg->arch_env, res, &ia32_fp_cw_regs[REG_FPCW]); + break; + } + + return res; } /** @@ -4593,11 +4685,16 @@ static void add_missing_keep_walker(ir_node *node, void *data) assert(n_outs < (int) sizeof(unsigned) * 8); foreach_out_edge(node, edge) { ir_node *proj = get_edge_src_irn(edge); - int pn = get_Proj_proj(proj); + int pn; + + /* The node could be kept */ + if (is_End(proj)) + continue; if (get_irn_mode(proj) == mode_M) continue; + pn = get_Proj_proj(proj); assert(pn < n_outs); found_projs |= 1 << pn; } diff --git a/ir/be/ia32/ia32_x87.c b/ir/be/ia32/ia32_x87.c index 080d331e0..9a6b1d42f 100644 --- a/ir/be/ia32/ia32_x87.c +++ b/ir/be/ia32/ia32_x87.c @@ -1913,7 +1913,7 @@ static ir_node *get_call_result_proj(ir_node *call) { ir_node *proj = get_edge_src_irn(edge); long pn = get_Proj_proj(proj); - if (pn == pn_be_Call_first_res) { + if (pn == pn_ia32_Call_vf0) { return proj; } } @@ -1922,7 +1922,7 @@ static ir_node *get_call_result_proj(ir_node *call) { } /* get_call_result_proj */ /** - * Simulate a be_Call. + * Simulate a ia32_Call. * * @param state the x87 state * @param n the node that should be simulated @@ -1931,7 +1931,7 @@ static ir_node *get_call_result_proj(ir_node *call) { */ static int sim_Call(x87_state *state, ir_node *n) { - ir_type *call_tp = be_Call_get_type(n); + ir_type *call_tp = get_ia32_call_attr_const(n)->call_tp; ir_type *res_type; ir_mode *mode; ir_node *resproj; @@ -2354,6 +2354,7 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg, /* set the generic function pointer of instruction we must simulate */ clear_irp_opcodes_generic_func(); + register_sim(op_ia32_Call, sim_Call); register_sim(op_ia32_vfld, sim_fld); register_sim(op_ia32_vfild, sim_fild); register_sim(op_ia32_vfld1, sim_fld1); @@ -2372,7 +2373,6 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg, register_sim(op_ia32_vFucomFnstsw, sim_Fucom); register_sim(op_ia32_vFucomi, sim_Fucom); register_sim(op_be_Copy, sim_Copy); - register_sim(op_be_Call, sim_Call); register_sim(op_be_Spill, sim_Spill); register_sim(op_be_Reload, sim_Reload); register_sim(op_be_Return, sim_Return);