+ bitset_t *used_proj_nr;
+ DEBUG_ONLY(firm_dbg_module_t *dbg = env->dbg;)
+
+ DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg));
+
+ /* set the links of all frame entities to NULL, we use it
+ to detect if an entity is already linked in the value_param_list */
+ tp = get_method_value_param_type(method_type);
+ if (tp != NULL) {
+ for (i = get_struct_n_members(tp) - 1; i >= 0; --i)
+ set_entity_link(get_struct_member(tp, i), NULL);
+ }
+
+ /* Convert the Sel nodes in the irg to frame load/store/addr nodes. */
+ ctx.env = env;
+ ctx.value_param_list = NULL;
+ ctx.value_param_tail = 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);
+ 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);
+ if (! is_Anchor(irn)) {
+ 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), arch_env->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_env_get_n_reg_class(arch_env); i < n; ++i) {
+ const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, 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 *) arch_env->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, 0);
+ be_abi_reg_map_set(env->regs, sp, env->init_sp);
+
+ 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);
+ ir_mode *mode;
+
+ 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) {
+ ir_node *addr = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);
+
+ /* For atomic parameters which are actually used, we create a Load node. */
+ if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
+ ir_mode *mode = get_type_mode(param_type);
+ ir_mode *load_mode = arg->load_mode;
+
+ ir_node *load = new_r_Load(irg, reg_params_bl, new_NoMem(), addr, load_mode);
+ set_irn_pinned(load, op_pin_state_floats);
+ repl = new_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
+
+ if (mode != load_mode) {
+ repl = new_r_Conv(irg, reg_params_bl, repl, mode);
+ }
+ } else {
+ /* 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. */
+ repl = addr;
+ }
+ }
+
+ assert(repl != NULL);
+
+ /* Beware: the mode of the register parameters is always the mode of the register class
+ which may be wrong. Add Conv's then. */
+ mode = get_irn_mode(args[i]);
+ if (mode != get_irn_mode(repl)) {
+ repl = new_r_Conv(irg, get_irn_n(repl, -1), repl, mode);
+ }
+ exchange(args[i], repl);
+ }
+ }
+
+ /* the arg proj is not needed anymore now and should be only used by the anchor */
+ assert(get_irn_n_edges(arg_tuple) == 1);
+ kill_node(arg_tuple);
+ set_irg_args(irg, new_rd_Bad(irg));
+
+ /* All Return nodes hang on the End node, so look for them there. */
+ for (i = 0, n = get_Block_n_cfgpreds(end); i < n; ++i) {
+ ir_node *irn = get_Block_cfgpred(end, i);
+
+ if (is_Return(irn)) {
+ ir_node *blk = get_nodes_block(irn);
+ ir_node *mem = get_Return_mem(irn);
+ ir_node *ret = create_be_return(env, irn, blk, mem, get_Return_n_ress(irn));
+ exchange(irn, ret);
+ }
+ }
+ /* if we have endless loops here, n might be <= 0. Do NOT create a be_Return then,
+ the code is dead and will never be executed. */
+
+ del_pset(dont_save);
+ obstack_free(&env->obst, args);
+
+ /* handle start block here (place a jump in the block) */
+ i = 0;
+ irg_block_walk_graph(irg, fix_start_block, NULL, &i);
+}
+
+/** Fix the state inputs of calls that still hang on unknowns */
+static
+void fix_call_state_inputs(be_abi_irg_t *env)
+{
+ const arch_env_t *arch_env = env->arch_env;
+ int i, n, n_states;
+ arch_register_t **stateregs = NEW_ARR_F(arch_register_t*, 0);
+
+ /* Collect caller save registers */
+ n = arch_env_get_n_reg_class(arch_env);
+ for(i = 0; i < n; ++i) {
+ unsigned j;
+ const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, i);
+ for(j = 0; j < cls->n_regs; ++j) {
+ const arch_register_t *reg = arch_register_for_index(cls, j);
+ if(arch_register_type_is(reg, state)) {
+ ARR_APP1(arch_register_t*, stateregs, (arch_register_t *)reg);
+ }
+ }
+ }
+
+ n = ARR_LEN(env->calls);
+ n_states = ARR_LEN(stateregs);
+ for(i = 0; i < n; ++i) {
+ int s, arity;
+ ir_node *call = env->calls[i];
+
+ arity = get_irn_arity(call);
+
+ /* the state reg inputs are the last n inputs of the calls */
+ for(s = 0; s < n_states; ++s) {
+ int inp = arity - n_states + s;
+ const arch_register_t *reg = stateregs[s];
+ ir_node *regnode = be_abi_reg_map_get(env->regs, reg);
+
+ set_irn_n(call, inp, regnode);
+ }
+ }
+
+ DEL_ARR_F(stateregs);
+}
+
+/**
+ * Create a trampoline entity for the given method.
+ */
+static ir_entity *create_trampoline(be_main_env_t *be, ir_entity *method)
+{
+ ir_type *type = get_entity_type(method);
+ ident *old_id = get_entity_ld_ident(method);
+ ident *id = mangle3("L", old_id, "$stub");
+ ir_type *parent = be->pic_trampolines_type;
+ ir_entity *ent = new_entity(parent, old_id, type);
+ set_entity_ld_ident(ent, id);
+ set_entity_visibility(ent, visibility_local);
+ set_entity_variability(ent, variability_uninitialized);
+
+ return ent;
+}
+
+/**
+ * Returns the trampoline entity for the given method.
+ */
+static ir_entity *get_trampoline(be_main_env_t *env, ir_entity *method)
+{
+ ir_entity *result = pmap_get(env->ent_trampoline_map, method);
+ if (result == NULL) {
+ result = create_trampoline(env, method);
+ pmap_insert(env->ent_trampoline_map, method, result);
+ }
+
+ return result;
+}
+
+/**
+ * Returns non-zero if a given entity can be accessed using a relative address.
+ */
+static int can_address_relative(ir_entity *entity)
+{
+ return get_entity_variability(entity) == variability_initialized
+ || get_entity_visibility(entity) == visibility_local;
+}
+
+/** patches SymConsts to work in position independent code */
+static void fix_pic_symconsts(ir_node *node, void *data)
+{
+ ir_graph *irg;
+ ir_node *pic_base;
+ ir_node *add;
+ ir_node *block;
+ ir_node *unknown;
+ ir_mode *mode;
+ ir_node *load;
+ ir_node *load_res;
+ be_abi_irg_t *env = data;
+ int arity, i;
+ be_main_env_t *be = env->birg->main_env;
+
+ arity = get_irn_arity(node);
+ for (i = 0; i < arity; ++i) {
+ ir_node *pred = get_irn_n(node, i);
+ ir_entity *entity;
+ if (!is_SymConst(pred))
+ continue;
+
+ entity = get_SymConst_entity(pred);
+ block = get_nodes_block(pred);
+ irg = get_irn_irg(pred);
+
+ /* calls can jump to relative addresses, so we can directly jump to
+ the (relatively) known call address or the trampoline */
+ if (is_Call(node) && i == 1) {
+ dbg_info *dbgi;
+ ir_entity *trampoline;
+ ir_node *trampoline_const;
+
+ if (can_address_relative(entity))
+ continue;
+
+ dbgi = get_irn_dbg_info(pred);
+ trampoline = get_trampoline(be, entity);
+ trampoline_const = new_rd_SymConst_addr_ent(dbgi, irg, mode_P_code, trampoline, NULL);
+ set_irn_n(node, i, trampoline_const);
+ continue;
+ }
+
+ /* everything else is accessed relative to EIP */
+ mode = get_irn_mode(pred);
+ unknown = new_r_Unknown(irg, mode);
+ pic_base = arch_code_generator_get_pic_base(env->birg->cg);
+ add = new_r_Add(irg, block, pic_base, pred, mode);
+
+ /* make sure the walker doesn't visit this add again */
+ mark_irn_visited(add);
+
+ /* all ok now for locally constructed stuff */
+ if (can_address_relative(entity)) {
+ set_irn_n(node, i, add);
+ continue;
+ }
+
+ /* 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 */
+ load = new_r_Load(irg, block, new_NoMem(), add, mode);
+ load_res = new_r_Proj(irg, block, load, mode, pn_Load_res);
+ set_irn_pinned(load, op_pin_state_floats);
+
+ set_irn_n(node, i, load_res);
+ }
+}
+
+be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
+{
+ be_abi_irg_t *env = xmalloc(sizeof(env[0]));
+ ir_node *old_frame = get_irg_frame(birg->irg);
+ ir_graph *irg = birg->irg;
+
+ pmap_entry *ent;
+ ir_node *dummy;
+ optimization_state_t state;
+ unsigned *limited_bitset;
+
+ be_omit_fp = birg->main_env->options->omit_fp;
+ be_omit_leaf_fp = birg->main_env->options->omit_leaf_fp;
+
+ obstack_init(&env->obst);
+
+ env->arch_env = birg->main_env->arch_env;
+ env->method_type = get_entity_type(get_irg_entity(irg));
+ env->call = be_abi_call_new(env->arch_env->sp->reg_class);
+ arch_env_get_call_abi(env->arch_env, env->method_type, env->call);
+
+ env->ignore_regs = pset_new_ptr_default();
+ env->keep_map = pmap_create();
+ env->dce_survivor = new_survive_dce();
+ env->birg = birg;
+
+ env->sp_req.type = arch_register_req_type_limited;
+ env->sp_req.cls = arch_register_get_class(env->arch_env->sp);
+ limited_bitset = rbitset_obstack_alloc(&env->obst, env->sp_req.cls->n_regs);
+ rbitset_set(limited_bitset, arch_register_get_index(env->arch_env->sp));
+ env->sp_req.limited = limited_bitset;
+
+ env->sp_cls_req.type = arch_register_req_type_normal;
+ env->sp_cls_req.cls = arch_register_get_class(env->arch_env->sp);
+
+ /* Beware: later we replace this node by the real one, ensure it is not CSE'd
+ to another Unknown or the stack pointer gets used */
+ save_optimization_state(&state);
+ set_optimize(0);
+ env->init_sp = dummy = new_r_Unknown(irg, env->arch_env->sp->reg_class->mode);
+ restore_optimization_state(&state);
+ FIRM_DBG_REGISTER(env->dbg, "firm.be.abi");
+
+ env->calls = NEW_ARR_F(ir_node*, 0);
+
+ if (birg->main_env->options->pic) {
+ irg_walk_graph(irg, fix_pic_symconsts, NULL, env);
+ }
+
+ /* Lower all call nodes in the IRG. */
+ process_calls(env);
+
+ /*
+ Beware: init backend abi call object after processing calls,
+ otherwise some information might be not yet available.
+ */
+ env->cb = env->call->cb->init(env->call, birg->main_env->arch_env, irg);
+
+ /* Process the IRG */
+ modify_irg(env);
+
+ /* fix call inputs for state registers */
+ fix_call_state_inputs(env);
+
+ /* We don't need the keep map anymore. */
+ pmap_destroy(env->keep_map);
+ env->keep_map = NULL;
+
+ /* calls array is not needed anymore */
+ DEL_ARR_F(env->calls);
+ env->calls = NULL;
+
+ /* reroute the stack origin of the calls to the true stack origin. */
+ exchange(dummy, env->init_sp);
+ exchange(old_frame, get_irg_frame(irg));
+
+ /* Make some important node pointers survive the dead node elimination. */
+ survive_dce_register_irn(env->dce_survivor, &env->init_sp);
+ foreach_pmap(env->regs, ent) {
+ survive_dce_register_irn(env->dce_survivor, (ir_node **) &ent->value);
+ }
+
+ env->call->cb->done(env->cb);
+ env->cb = NULL;
+ return env;
+}