calling_convention_t *sparc_prepare_calling_convention(ir_graph *const irg) { ir_entity *const entity = get_irg_entity(irg); ir_type *const non_lowered = get_entity_type(entity); calling_convention_t *cconv = sparc_decide_calling_convention(get_entity_type(entity), irg); if (sparc_variadic_fixups(irg, cconv)) { sparc_free_calling_convention(cconv); cconv = sparc_decide_calling_convention(get_entity_type(entity), irg); } sparc_layout_param_entities(irg, cconv, non_lowered); return cconv; }
void analyze_irg_args(ir_graph *irg) { if (irg == get_const_code_irg()) return; ir_entity *entity = get_irg_entity(irg); if (! entity) return; if (! entity->attr.mtd_attr.param_access) analyze_ent_args(entity); }
/** * For debugging. call *compare_iv() and prints inputs and result. * * @param l_iv the left interval * @param r_iv the right interval * @param relation the compare relation */ static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation) { tarval *tv = (compare_iv)(l_iv, r_iv, relation); if (tv == tarval_bad) return tv; ir_printf("In %e:\n", get_irg_entity(current_ir_graph)); print_iv_cmp(l_iv, r_iv, relation); ir_printf(" = %T\n", tv); return tv; }
/** * count the DAG's size of a graph * * @param global the global entry * @param graph the current graph entry */ void count_dags_in_graph(graph_entry_t *global, graph_entry_t *graph) { dag_env_t root_env; dag_entry_t *entry; unsigned id; (void) global; /* do NOT check the const code irg */ if (graph->irg == get_const_code_irg()) return; /* first step, clear the links */ irg_walk_graph(graph->irg, firm_clear_link, NULL, NULL); obstack_init(&root_env.obst); root_env.num_of_dags = 0; root_env.list_of_dags = NULL; root_env.options = FIRMSTAT_COPY_CONSTANTS | FIRMSTAT_LOAD_IS_LEAVE | FIRMSTAT_CALL_IS_LEAVE; /* find the DAG roots that are referenced from other block */ irg_walk_graph(graph->irg, NULL, find_dag_roots, &root_env); /* connect and count them */ irg_walk_graph(graph->irg, connect_dags, NULL, &root_env); printf("Graph %p %s --- %u\n", (void *)graph->irg, get_entity_name(get_irg_entity(graph->irg)), root_env.num_of_dags); for (id = 0, entry = root_env.list_of_dags; entry; entry = entry->next) { if (entry->is_dead) continue; entry->id = id++; printf("number of roots %u number of nodes %u inner %u tree %u %ld\n", entry->num_roots, entry->num_nodes, entry->num_inner_nodes, (unsigned)entry->is_tree, get_irn_node_nr(entry->root)); } /* dump for test */ mark_options = root_env.options; set_dump_node_vcgattr_hook(stat_dag_mark_hook); dump_ir_graph(graph->irg, "dag"); set_dump_node_vcgattr_hook(NULL); assert(id == root_env.num_of_dags); obstack_free(&root_env.obst, NULL); }
void analyze_irg_args_weight(ir_graph *irg) { ir_entity *entity = get_irg_entity(irg); if (entity == NULL) return; assert(is_method_entity(entity)); if (entity->attr.mtd_attr.param_weight != NULL) return; ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED); inc_irg_visited(irg); analyze_method_params_weight(entity); ir_free_resources(irg, IR_RESOURCE_IRN_VISITED); }
static void sparc_layout_param_entities(ir_graph *const irg, calling_convention_t *const cconv, ir_type *const non_lowered) { ir_entity **const param_map = be_collect_parameter_entities(irg); ir_type *const frame_type = get_irg_frame_type(irg); size_t const n_params = cconv->n_parameters; /* calculate offsets/create missing entities */ for (size_t i = 0; i < n_params; ++i) { reg_or_stackslot_t *const param = &cconv->parameters[i]; ir_entity * entity = param_map[i]; if (entity == NULL) { if (!param->already_stored) continue; entity = new_parameter_entity(frame_type, i, param->type); } param->entity = entity; set_entity_offset(entity, param->offset); } ir_entity *const function = get_irg_entity(irg); ir_type *const function_type = get_entity_type(function); if (is_method_variadic(function_type)) { ir_type *unknown = get_unknown_type(); ident *id = new_id_from_str("$va_start"); ir_entity *va_start_addr = new_entity(frame_type, id, unknown); /* sparc_variadic_fixups() fiddled with our type, find out the * original number of parameters */ size_t const orig_n_params = get_method_n_params(non_lowered); long offset; if (orig_n_params < n_params) { assert(param_map[orig_n_params] != NULL); offset = get_entity_offset(param_map[orig_n_params]); } else { offset = cconv->param_stack_size + SPARC_MIN_STACKSIZE; } set_entity_offset(va_start_addr, offset); cconv->va_start_addr = va_start_addr; } free(param_map); }
/** * Perform some fixups for variadic functions. * To make the rest of the frontend code easier to understand we add * "dummy" parameters until the number of parameters transmitted in registers. * (because otherwise the backend wouldn't store the value of the register * parameters into memory for the VLA magic) */ static bool sparc_variadic_fixups(ir_graph *const irg, calling_convention_t *const cconv) { ir_entity *entity = get_irg_entity(irg); ir_type *mtp = get_entity_type(entity); if (!is_method_variadic(mtp)) return false; if (cconv->n_param_regs >= SPARC_N_PARAM_REGS) return false; size_t const n_params = get_method_n_params(mtp); size_t const n_ress = get_method_n_ress(mtp); size_t const new_n_params = n_params + (SPARC_N_PARAM_REGS - cconv->n_param_regs); unsigned const cc_mask = get_method_calling_convention(mtp); mtp_additional_properties const props = get_method_additional_properties(mtp); ir_type *const new_mtp = new_type_method(new_n_params, n_ress, true, cc_mask, props); type_dbg_info *const dbgi = get_type_dbg_info(mtp); set_type_dbg_info(new_mtp, dbgi); for (size_t i = 0; i < n_ress; ++i) { ir_type *type = get_method_res_type(mtp, i); set_method_res_type(new_mtp, i, type); } for (size_t i = 0; i < n_params; ++i) { ir_type *type = get_method_param_type(mtp, i); set_method_param_type(new_mtp, i, type); } ir_type *const frame_type = get_irg_frame_type(irg); ir_mode *const gp_reg_mode = sparc_reg_classes[CLASS_sparc_gp].mode; ir_type *const gp_reg_type = get_type_for_mode(gp_reg_mode); for (size_t i = n_params; i < new_n_params; ++i) { set_method_param_type(new_mtp, i, gp_reg_type); new_parameter_entity(frame_type, i, gp_reg_type); } set_entity_type(entity, new_mtp); return true; }
int check_entity(const ir_entity *entity) { bool fine = true; ir_linkage linkage = get_entity_linkage(entity); if (linkage & IR_LINKAGE_NO_CODEGEN) { if (!is_method_entity(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity); fine = false; } else if (get_entity_irg(entity) == NULL) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity); fine = false; } if (!is_externally_visible(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity); fine = false; } } check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK"); check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT, "GARBAGE_COLLECT"); check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE"); ir_type const *const type = get_entity_type(entity); ir_type const *const owner = get_entity_owner(entity); switch (get_entity_kind(entity)) { case IR_ENTITY_ALIAS: if (!is_segment_type(owner)) { report_error("alias entity %+F has non-segment owner %+F", entity, owner); fine = false; } break; case IR_ENTITY_NORMAL: { ir_initializer_t const *const init = get_entity_initializer(entity); if (init) fine &= check_initializer(init, type, entity); if (!is_data_type(type)) { report_error("normal entity %+F has non-data type %+F", entity, type); fine = false; } break; } case IR_ENTITY_COMPOUND_MEMBER: if (!is_compound_type(owner)) { report_error("compound member entity %+F has non-compound owner %+F", entity, owner); fine = false; } break; case IR_ENTITY_LABEL: if (type != get_code_type()) { report_error("label entity %+F has non-code type %+F", entity, type); fine = false; } break; case IR_ENTITY_METHOD: if (!is_Method_type(type)) { report_error("method entity %+F has non-method type %+F", entity, type); fine = false; } ir_graph *irg = get_entity_irg(entity); if (irg != NULL) { ir_entity *irg_entity = get_irg_entity(irg); if (irg_entity != entity) { report_error("entity(%+F)->irg->entity(%+F) relation invalid", entity, irg_entity); fine = false; } } break; case IR_ENTITY_PARAMETER: if (!is_frame_type(owner)) { report_error("parameter entity %+F has non-frame owner %+F", entity, owner); fine = false; } if (!is_data_type(type)) { report_error("parameter entity %+F has non-data type %+F", entity, type); fine = false; } break; case IR_ENTITY_UNKNOWN: break; case IR_ENTITY_SPILLSLOT: if (is_frame_type(owner)) { report_error("spillslot %+F must be on frame type", entity); fine = false; } break; } if (is_frame_type(owner) && entity_has_definition(entity)) { report_error("entity %+F on frame %+F has initialized", entity, owner); fine = false; } return fine; }
/* * Normalize the Returns of a graph by creating a new End block * with One Return(Phi). * This is the preferred input for the if-conversion. * * In pseudocode, it means: * * if (a) * return b; * else * return c; * * is transformed into * * if (a) * res = b; * else * res = c; * return res; */ void normalize_one_return(ir_graph *irg) { ir_node *endbl = get_irg_end_block(irg); ir_entity *entity = get_irg_entity(irg); ir_type *type = get_entity_type(entity); int n_ret_vals = get_method_n_ress(type) + 1; int n_rets = 0; bool filter_dbgi = false; dbg_info *combined_dbgi = NULL; int i, j, k, n, last_idx; ir_node **in, **retvals, **endbl_in; ir_node *block; /* look, if we have more than one return */ n = get_Block_n_cfgpreds(endbl); if (n <= 0) { /* The end block has no predecessors, we have an endless loop. In that case, no returns exists. */ confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL); add_irg_properties(irg, IR_GRAPH_PROPERTY_ONE_RETURN); return; } unsigned *const returns = rbitset_alloca(n); for (i = 0; i < n; ++i) { ir_node *node = get_Block_cfgpred(endbl, i); if (is_Return(node)) { dbg_info *dbgi = get_irn_dbg_info(node); if (dbgi != NULL && dbgi != combined_dbgi) { if (filter_dbgi) { combined_dbgi = NULL; } else { combined_dbgi = dbgi; filter_dbgi = true; } } ++n_rets; rbitset_set(returns, i); } } if (n_rets <= 1) { confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL); add_irg_properties(irg, IR_GRAPH_PROPERTY_ONE_RETURN); return; } in = ALLOCAN(ir_node*, MAX(n_rets, n_ret_vals)); retvals = ALLOCAN(ir_node*, n_rets * n_ret_vals); endbl_in = ALLOCAN(ir_node*, n); last_idx = 0; for (j = i = 0; i < n; ++i) { ir_node *ret = get_Block_cfgpred(endbl, i); if (rbitset_is_set(returns, i)) { ir_node *block = get_nodes_block(ret); /* create a new Jmp for every Ret and place the in in */ in[j] = new_r_Jmp(block); /* save the return values and shuffle them */ for (k = 0; k < n_ret_vals; ++k) retvals[j + k*n_rets] = get_irn_n(ret, k); ++j; } else { endbl_in[last_idx++] = ret; } } /* ok, create a new block with all created in's */ block = new_r_Block(irg, n_rets, in); /* now create the Phi nodes */ for (j = i = 0; i < n_ret_vals; ++i, j += n_rets) { ir_mode *mode = get_irn_mode(retvals[j]); in[i] = new_r_Phi(block, n_rets, &retvals[j], mode); } endbl_in[last_idx++] = new_rd_Return(combined_dbgi, block, in[0], n_ret_vals-1, &in[1]); set_irn_in(endbl, last_idx, endbl_in); /* invalidate analysis information: * a new Block was added, so dominator, outs and loop are inconsistent, * trouts and callee-state should be still valid */ confirm_irg_properties(irg, IR_GRAPH_PROPERTY_NO_BADS | IR_GRAPH_PROPERTY_NO_TUPLES | IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES | IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE | IR_GRAPH_PROPERTY_CONSISTENT_ENTITY_USAGE); add_irg_properties(irg, IR_GRAPH_PROPERTY_ONE_RETURN); }
int check_entity(const ir_entity *entity) { bool fine = true; ir_type *tp = get_entity_type(entity); ir_linkage linkage = get_entity_linkage(entity); fine &= constants_on_wrong_irg(entity); if (is_method_entity(entity)) { ir_graph *irg = get_entity_irg(entity); if (irg != NULL) { ir_entity *irg_entity = get_irg_entity(irg); if (irg_entity != entity) { report_error("entity(%+F)->irg->entity(%+F) relation invalid", entity, irg_entity); fine = false; } } if (get_entity_peculiarity(entity) == peculiarity_existent) { ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity)); if (impl == NULL) { report_error("inherited method entity %+F must have constant pointing to existent entity.", entity); fine = false; } } } if (linkage & IR_LINKAGE_NO_CODEGEN) { if (!is_method_entity(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity); fine = false; } else if (get_entity_irg(entity) == NULL) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity); fine = false; } if (get_entity_visibility(entity) != ir_visibility_external) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity); fine = false; } } check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK"); check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT, "GARBAGE_COLLECT"); check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE"); if (is_atomic_entity(entity) && entity->initializer != NULL) { ir_mode *mode = NULL; ir_initializer_t *initializer = entity->initializer; switch (initializer->kind) { case IR_INITIALIZER_CONST: mode = get_irn_mode(get_initializer_const_value(initializer)); break; case IR_INITIALIZER_TARVAL: mode = get_tarval_mode(get_initializer_tarval_value(initializer)); break; case IR_INITIALIZER_NULL: case IR_INITIALIZER_COMPOUND: break; } if (mode != NULL && mode != get_type_mode(tp)) { report_error("initializer of entity %+F has wrong mode.", entity); fine = false; } } return fine; }