+static int determine_ebp_input(ir_node *ret)
+{
+ const arch_register_t *bp = &ia32_registers[REG_EBP];
+ int arity = get_irn_arity(ret);
+ int i;
+
+ for (i = 0; i < arity; ++i) {
+ ir_node *input = get_irn_n(ret, i);
+ if (arch_get_irn_register(input) == bp)
+ return i;
+ }
+ panic("no ebp input found at %+F", ret);
+}
+
+static void introduce_epilog(ir_node *ret)
+{
+ const arch_register_t *sp = &ia32_registers[REG_ESP];
+ const arch_register_t *bp = &ia32_registers[REG_EBP];
+ ir_graph *irg = get_irn_irg(ret);
+ ir_type *frame_type = get_irg_frame_type(irg);
+ unsigned frame_size = get_type_size_bytes(frame_type);
+ be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
+ ir_node *block = get_nodes_block(ret);
+ ir_node *first_sp = get_irn_n(ret, n_be_Return_sp);
+ ir_node *curr_sp = first_sp;
+ ir_mode *mode_gp = mode_Iu;
+
+ if (!layout->sp_relative) {
+ int n_ebp = determine_ebp_input(ret);
+ ir_node *curr_bp = get_irn_n(ret, n_ebp);
+ if (ia32_cg_config.use_leave) {
+ ir_node *leave = new_bd_ia32_Leave(NULL, block, curr_bp);
+ curr_bp = new_r_Proj(leave, mode_gp, pn_ia32_Leave_frame);
+ curr_sp = new_r_Proj(leave, mode_gp, pn_ia32_Leave_stack);
+ arch_set_irn_register(curr_bp, bp);
+ arch_set_irn_register(curr_sp, sp);
+ sched_add_before(ret, leave);
+ } else {
+ ir_node *pop;
+ ir_node *curr_mem = get_irn_n(ret, n_be_Return_mem);
+ /* copy ebp to esp */
+ curr_sp = new_bd_ia32_CopyEbpEsp(NULL, block, curr_bp);
+ arch_set_irn_register(curr_sp, sp);
+ sched_add_before(ret, curr_sp);
+
+ /* pop ebp */
+ pop = new_bd_ia32_PopEbp(NULL, block, curr_mem, curr_sp);
+ curr_bp = new_r_Proj(pop, mode_gp, pn_ia32_PopEbp_res);
+ curr_sp = new_r_Proj(pop, mode_gp, pn_ia32_PopEbp_stack);
+ curr_mem = new_r_Proj(pop, mode_M, pn_ia32_Pop_M);
+ arch_set_irn_register(curr_bp, bp);
+ arch_set_irn_register(curr_sp, sp);
+ sched_add_before(ret, pop);
+
+ set_irn_n(ret, n_be_Return_mem, curr_mem);
+ }
+ set_irn_n(ret, n_ebp, curr_bp);
+ } else {
+ ir_node *incsp = be_new_IncSP(sp, block, curr_sp, -(int)frame_size, 0);
+ sched_add_before(ret, incsp);
+ curr_sp = incsp;
+ }
+ set_irn_n(ret, n_be_Return_sp, curr_sp);
+
+ /* keep verifier happy... */
+ if (get_irn_n_edges(first_sp) == 0 && is_Proj(first_sp)) {
+ kill_node(first_sp);
+ }
+}
+