+ DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg));
+
+ /* Convert the Sel nodes in the irg to frame load/store/addr nodes. */
+ ctx.env = env;
+ ctx.value_param_list = NULL;
+ irg_walk_graph(irg, lower_frame_sels_walker, NULL, &ctx);
+
+ /* value_param_base anchor is not needed anymore now */
+ value_param_base = get_irg_value_param_base(irg);
+ be_kill_node(value_param_base);
+ set_irg_value_param_base(irg, new_r_Bad(irg));
+
+ env->frame = obstack_alloc(&env->obst, sizeof(env->frame[0]));
+ env->regs = pmap_create();
+
+ used_proj_nr = bitset_alloca(1024);
+ n_params = get_method_n_params(method_type);
+ args = obstack_alloc(&env->obst, n_params * sizeof(args[0]));
+ memset(args, 0, n_params * sizeof(args[0]));
+
+ /* Check if a value parameter is transmitted as a register.
+ * This might happen if the address of an parameter is taken which is
+ * transmitted in registers.
+ *
+ * Note that on some architectures this case must be handled specially
+ * because the place of the backing store is determined by their ABI.
+ *
+ * In the default case we move the entity to the frame type and create
+ * a backing store into the first block.
+ */
+ fix_address_of_parameter_access(env, ctx.value_param_list);
+
+ /* Fill the argument vector */
+ arg_tuple = get_irg_args(irg);
+ foreach_out_edge(arg_tuple, edge) {
+ ir_node *irn = get_edge_src_irn(edge);
+ int nr = get_Proj_proj(irn);
+ args[nr] = irn;
+ DBG((dbg, LEVEL_2, "\treading arg: %d -> %+F\n", nr, irn));
+ }
+
+ arg_type = compute_arg_type(env, call, method_type, ¶m_map);
+ bet_type = call->cb->get_between_type(env->cb);
+ stack_frame_init(env->frame, arg_type, bet_type, get_irg_frame_type(irg), isa->stack_dir, param_map);
+
+ /* Count the register params and add them to the number of Projs for the RegParams node */
+ for(i = 0; i < n_params; ++i) {
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
+ if(arg->in_reg && args[i]) {
+ assert(arg->reg != sp && "cannot use stack pointer as parameter register");
+ assert(i == get_Proj_proj(args[i]));
+
+ /* For now, associate the register with the old Proj from Start representing that argument. */
+ pmap_insert(env->regs, (void *) arg->reg, args[i]);
+ bitset_set(used_proj_nr, i);
+ DBG((dbg, LEVEL_2, "\targ #%d -> reg %s\n", i, arg->reg->name));
+ }
+ }
+
+ /* Collect all callee-save registers */
+ for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
+ const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
+ for(j = 0; j < cls->n_regs; ++j) {
+ const arch_register_t *reg = &cls->regs[j];
+ if(arch_register_type_is(reg, callee_save) ||
+ arch_register_type_is(reg, state)) {
+ pmap_insert(env->regs, (void *) reg, NULL);
+ }
+ }
+ }
+
+ pmap_insert(env->regs, (void *) sp, NULL);
+ pmap_insert(env->regs, (void *) isa->bp, NULL);
+ reg_params_bl = get_irg_start_block(irg);
+ env->reg_params = be_new_RegParams(irg, reg_params_bl, pmap_count(env->regs));
+ add_irn_dep(env->reg_params, get_irg_start(irg));
+
+ /*
+ * make proj nodes for the callee save registers.
+ * memorize them, since Return nodes get those as inputs.
+ *
+ * Note, that if a register corresponds to an argument, the regs map contains
+ * the old Proj from start for that argument.
+ */
+
+ rm = reg_map_to_arr(&env->obst, env->regs);
+ for(i = 0, n = pmap_count(env->regs); i < n; ++i) {
+ arch_register_t *reg = (void *) rm[i].reg;
+ ir_mode *mode = reg->reg_class->mode;
+ long nr = i;
+ int pos = BE_OUT_POS((int) nr);
+ int flags = 0;
+
+ ir_node *proj;
+
+ assert(nr >= 0);
+ bitset_set(used_proj_nr, nr);
+ proj = new_r_Proj(irg, reg_params_bl, env->reg_params, mode, nr);
+ pmap_insert(env->regs, (void *) reg, proj);
+ be_set_constr_single_reg(env->reg_params, pos, reg);
+ arch_set_irn_register(env->birg->main_env->arch_env, proj, reg);
+
+ /*
+ * If the register is an ignore register,
+ * The Proj for that register shall also be ignored during register allocation.
+ */
+ if(arch_register_type_is(reg, ignore))
+ flags |= arch_irn_flags_ignore;
+
+ if(reg == sp)
+ flags |= arch_irn_flags_modify_sp;
+
+ be_node_set_flags(env->reg_params, pos, flags);
+
+ DBG((dbg, LEVEL_2, "\tregister save proj #%d -> reg %s\n", nr, reg->name));
+ }
+ obstack_free(&env->obst, rm);
+
+ /* create a new initial memory proj */
+ assert(is_Proj(old_mem));
+ new_mem_proj = new_r_Proj(irg, get_nodes_block(old_mem),
+ new_r_Unknown(irg, mode_T), mode_M,
+ get_Proj_proj(old_mem));
+ mem = new_mem_proj;
+
+ /* Generate the Prologue */
+ fp_reg = call->cb->prologue(env->cb, &mem, env->regs);
+
+ /* do the stack allocation BEFORE the barrier, or spill code
+ might be added before it */
+ env->init_sp = be_abi_reg_map_get(env->regs, sp);
+ env->init_sp = be_new_IncSP(sp, irg, bl, env->init_sp, BE_STACK_FRAME_SIZE_EXPAND);
+ be_abi_reg_map_set(env->regs, sp, env->init_sp);
+
+ env->start_barrier = barrier = create_barrier(env, bl, &mem, env->regs, 0);
+
+ env->init_sp = be_abi_reg_map_get(env->regs, sp);
+ arch_set_irn_register(env->birg->main_env->arch_env, env->init_sp, sp);
+
+ frame_pointer = be_abi_reg_map_get(env->regs, fp_reg);
+ set_irg_frame(irg, frame_pointer);
+ pset_insert_ptr(env->ignore_regs, fp_reg);
+
+ /* rewire old mem users to new mem */
+ set_Proj_pred(new_mem_proj, get_Proj_pred(old_mem));
+ exchange(old_mem, mem);
+
+ set_irg_initial_mem(irg, mem);
+
+ /* Now, introduce stack param nodes for all parameters passed on the stack */
+ for(i = 0; i < n_params; ++i) {
+ ir_node *arg_proj = args[i];
+ ir_node *repl = NULL;
+
+ if(arg_proj != NULL) {
+ be_abi_call_arg_t *arg;
+ ir_type *param_type;
+ int nr = get_Proj_proj(arg_proj);
+
+ nr = MIN(nr, n_params);
+ arg = get_call_arg(call, 0, nr);
+ param_type = get_method_param_type(method_type, nr);
+
+ if(arg->in_reg) {
+ repl = pmap_get(env->regs, (void *) arg->reg);
+ }
+
+ else if(arg->on_stack) {
+ /* For atomic parameters which are actually used, we create a StackParam node. */
+ if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
+ ir_mode *mode = get_type_mode(param_type);
+ const arch_register_class_t *cls = arch_isa_get_reg_class_for_mode(isa, mode);
+ repl = be_new_StackParam(cls, isa->bp->reg_class, irg, reg_params_bl, mode, frame_pointer, arg->stack_ent);
+ }
+
+ /* The stack parameter is not primitive (it is a struct or array),
+ we thus will create a node representing the parameter's address
+ on the stack. */
+ else {
+ repl = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);