static void replace_with_call(ir_node *node) { widen_builtin(node); ir_type *const mtp = get_Builtin_type(node); ir_builtin_kind const kind = get_Builtin_kind(node); char const *const name = get_builtin_name(kind); ir_type *const arg1 = get_method_param_type(mtp, 0); char const *const machmode = get_gcc_machmode(arg1); ident *const id = new_id_fmt("__%s%s2", name, machmode); ir_entity *const entity = create_compilerlib_entity(get_id_str(id), mtp); dbg_info *const dbgi = get_irn_dbg_info(node); ir_node *const block = get_nodes_block(node); ir_node *const mem = get_Builtin_mem(node); ir_graph *const irg = get_irn_irg(node); ir_node *const callee = new_r_Address(irg, entity); int const n_params = get_Builtin_n_params(node); ir_node **const params = get_Builtin_param_arr(node); ir_node *const call = new_rd_Call(dbgi, block, mem, callee, n_params, params, mtp); ir_node *const call_mem = new_r_Proj(call, mode_M, pn_Call_M); ir_node *const call_ress = new_r_Proj(call, mode_T, pn_Call_T_result); ir_type *const res_type = get_method_res_type(mtp, 0); ir_mode *const res_mode = get_type_mode(res_type); ir_node *const call_res = new_r_Proj(call_ress, res_mode, 0); ir_node *const in[] = { [pn_Builtin_M] = call_mem, [pn_Builtin_max + 1] = call_res, };
static ir_node *get_memcpy_address(ir_graph *irg) { ident *id = new_id_from_str("memcpy"); ir_type *mt = get_memcpy_methodtype(); ir_entity *ent = create_compilerlib_entity(id, mt); return new_r_Address(irg, ent); }
ir_node *gcji_lookup_interface(ir_node *objptr, ir_type *iface, ir_entity *method, ir_graph *irg, ir_node *block, ir_node **mem) { ir_node *cur_mem = *mem; // we need the reference to the object's class$ field // first, dereference the vptr in order to get the vtable address. ir_entity *vptr_entity = get_vptr_entity(); ir_type *vptr_type = get_entity_type(vptr_entity); ir_node *vptr_addr = new_r_Member(block, objptr, vptr_entity); ir_node *vptr_load = new_r_Load(block, cur_mem, vptr_addr, mode_reference, vptr_type, cons_none); ir_node *vtable_addr = new_r_Proj(vptr_load, mode_reference, pn_Load_res); cur_mem = new_r_Proj(vptr_load, mode_M, pn_Load_M); // second, dereference vtable_addr (it points to the slot where the address of the class$ field is stored). ir_node *cd_load = new_r_Load(block, cur_mem, vtable_addr, mode_reference, vptr_type, cons_none); ir_node *cd_ref = new_r_Proj(cd_load, mode_reference, pn_Load_res); cur_mem = new_r_Proj(cd_load, mode_M, pn_Load_M); class_t *linked_class = (class_t*) oo_get_type_link(iface); method_t *linked_method = (method_t*) oo_get_entity_link(method); assert(linked_class && linked_method); constant_t *name_const = linked_class->constants[linked_method->name_index]; ir_entity *name_const_ent= gcji_emit_utf8_const(name_const, 1); ir_node *name_ref = new_r_Address(irg, name_const_ent); constant_t *desc_const = linked_class->constants[linked_method->descriptor_index]; ir_entity *desc_const_ent= gcji_emit_utf8_const(desc_const, 1); ir_node *desc_ref = new_r_Address(irg, desc_const_ent); ir_node *callee = new_r_Address(irg, gcj_lookup_interface_entity); ir_node *args[3] = { cd_ref, name_ref, desc_ref }; ir_type *call_type = get_entity_type(gcj_lookup_interface_entity); ir_node *call = new_r_Call(block, cur_mem, callee, 3, args, call_type); cur_mem = new_r_Proj(call, mode_M, pn_Call_M); ir_node *ress = new_r_Proj(call, mode_T, pn_Call_T_result); ir_node *res = new_r_Proj(ress, mode_reference, 0); *mem = cur_mem; return res; }
static void set_compound_init_entref(ir_initializer_t *init, size_t idx, ir_entity *entity) { if (entity == NULL) { set_compound_init_null(init, idx); return; } ir_graph *ccode = get_const_code_irg(); ir_node *node = new_r_Address(ccode, entity); set_compound_init_node(init, idx, node); }
static ir_node *gcji_get_runtime_classinfo_(ir_node *block, ir_node **mem, ir_type *type) { ir_entity *rtti_entity = gcji_get_rtti_entity(type); ir_graph *irg = get_irn_irg(block); if (rtti_entity != NULL) return new_r_Address(irg, rtti_entity); /* Arrays are represented as pointer types. We extract the base type, * get its classinfo and let gcj give the array type for that. * * gcj emits the type signature to the class' constant pool. During * class linking, the reference to the utf8const is replaced by the * reference to the appropriate class object. */ assert(is_Pointer_type(type)); unsigned n_pointer_levels = 0; ir_type *eltype = type; while (is_Pointer_type(eltype)) { ++n_pointer_levels; eltype = get_pointer_points_to_type(eltype); } if (!is_Primitive_type(eltype)) --n_pointer_levels; ir_entity *elem_cdf = gcji_get_rtti_entity(eltype); assert(elem_cdf != NULL); ir_node *array_class_ref = new_r_Address(irg, elem_cdf); for (unsigned d = 0; d < n_pointer_levels; d++) { array_class_ref = gcji_get_arrayclass(block, mem, array_class_ref); } return array_class_ref; }
static ir_node *get_vtable_ref(ir_type *type) { ir_entity *cls_vtable = oo_get_class_vtable_entity(type); if (cls_vtable == NULL) return NULL; ir_graph *ccode = get_const_code_irg(); ir_node *addr = new_r_Address(ccode, cls_vtable); unsigned offset = ddispatch_get_vptr_points_to_index() * get_mode_size_bytes(mode_reference); ir_mode *offset_mode = get_reference_offset_mode(mode_reference); ir_node *cnst = new_r_Const_long(ccode, offset_mode, offset); ir_node *block = get_r_cur_block(ccode); ir_node *add = new_r_Add(block, addr, cnst); return add; }
static ir_node *gcji_get_arrayclass(ir_node *block, ir_node **mem, ir_node *array_class_ref) { ir_graph *irg = get_irn_irg(block); ir_node *addr = new_r_Address(irg, gcj_get_array_class_entity); ir_node *null = new_r_Const(irg, get_mode_null(mode_reference)); ir_node *args[] = { array_class_ref, null }; ir_type *call_type = get_entity_type(gcj_get_array_class_entity); ir_node *call = new_r_Call(block, *mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *new_mem = new_Proj(call, mode_M, pn_Call_M); ir_node *ress = new_Proj(call, mode_T, pn_Call_T_result); ir_node *res = new_Proj(ress, mode_reference, 0); *mem = new_mem; return res; }
static ir_node *gcji_instanceof(ir_node *objptr, ir_type *classtype, ir_graph *irg, ir_node *block, ir_node **mem) { ir_node *jclass = gcji_get_runtime_classinfo_(block, mem, classtype); ir_node *addr = new_r_Address(irg, gcj_instanceof_entity); ir_node *args[] = { objptr, jclass }; ir_type *call_type = get_entity_type(gcj_instanceof_entity); ir_node *call = new_r_Call(block, *mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *new_mem = new_r_Proj(call, mode_M, pn_Call_M); ir_node *ress = new_r_Proj(call, mode_T, pn_Call_T_result); ir_node *call_res = new_r_Proj(ress, mode_int, 0); ir_node *zero = new_r_Const(irg, get_mode_null(mode_int)); ir_node *res = new_r_Cmp(block, call_res, zero, ir_relation_less_greater); *mem = new_mem; return res; }
static void add_pointer_in_jcr_segment(ir_entity *entity) { if (!create_jcr_segment) return; ir_type *segment = get_segment_type(IR_SEGMENT_JCR); ident *id = id_unique("jcr_ptr"); ir_entity *ptr = new_entity(segment, id, type_reference); ir_graph *irg = get_const_code_irg(); ir_node *val = new_r_Address(irg, entity); set_entity_ld_ident(ptr, new_id_from_chars("", 0)); set_entity_visibility(ptr, ir_visibility_private); set_entity_linkage(ptr, IR_LINKAGE_CONSTANT|IR_LINKAGE_HIDDEN_USER); set_entity_alignment(ptr, 1); ir_initializer_t *const init = create_initializer_const(val); set_entity_initializer(ptr, init); }
/** * @return An Address representing the function that replaces the given node. */ static ir_node *create_softfloat_address(const ir_node *n, const char *name) { ir_type *const method = get_softfloat_type(n); /* Parameter types. */ char const *first_param = ""; char const *second_param = ""; unsigned float_types = 0; unsigned double_types = 0; switch (get_method_n_params(method)) { case 2: { ir_type *const param_type = get_method_param_type(method, 1); ir_mode *const mode = get_type_mode(param_type); if (mode == mode_F) { second_param = "sf"; float_types++; } else if (mode == mode_D) { second_param = "df"; double_types++; } else if (mode == mode_Iu || mode == mode_Is) { second_param = "si"; } else if (mode == mode_Lu || mode == mode_Ls) { second_param = "di"; } } /* FALLTHROUGH */ case 1: { ir_type *const param_type = get_method_param_type(method, 0); ir_mode *const mode = get_type_mode(param_type); if (mode == mode_F) { first_param = float_types > 0 ? "" : "sf"; float_types++; } else if (mode == mode_D) { first_param = double_types > 0 ? "" : "df"; double_types++; } else if (mode == mode_Iu || mode == mode_Is) { first_param = "si"; } else if (mode == mode_Lu || mode == mode_Ls) { first_param = "di"; } break; } default: break; } /* Result type. */ char const *result = ""; ir_mode *const mode = is_Div(n) ? get_Div_resmode(n) : get_irn_mode(n); if (mode == mode_F) { result = float_types > 0 ? "" : "sf"; float_types++; } else if (mode == mode_D) { result = double_types > 0 ? "" : "df"; double_types++; } else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu || mode == mode_Is || mode == mode_Hs || mode == mode_Bs) result = "si"; else if (mode == mode_Lu || mode == mode_Ls) result = "di"; assert(float_types <= 3); assert(double_types <= 3); ident *const id = float_types + double_types > 1 ? new_id_fmt("__%s%s%s%s%u", name, first_param, second_param, result, float_types + double_types) : new_id_fmt("__%s%s%s%s", name, first_param, second_param, result); ir_graph *const irg = get_irn_irg(n); ir_entity *const ent = create_compilerlib_entity(id, method); return new_r_Address(irg, ent); }
static void lower_divmod(ir_node *node, ir_node *left, ir_node *right, ir_node *mem, ir_mode *mode, int res_offset) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_mode *node_mode = get_irn_mode(left); ir_entity *entity = mode_is_signed(node_mode) ? ldivmod : uldivmod; ir_type *mtp = get_entity_type(entity); ir_graph *irg = get_irn_irg(node); ir_node *addr = new_r_Address(irg, entity); ir_node *in[4]; if (arm_cg_config.big_endian) { in[0] = left_high; in[1] = left_low; in[2] = right_high; in[3] = right_low; } else { in[0] = left_low; in[1] = left_high; in[2] = right_low; in[3] = right_high; } ir_node *call = new_rd_Call(dbgi, block, mem, addr, ARRAY_SIZE(in), in, mtp); ir_node *resproj = new_r_Proj(call, mode_T, pn_Call_T_result); set_irn_pinned(call, get_irn_pinned(node)); foreach_out_edge_safe(node, edge) { ir_node *proj = get_edge_src_irn(edge); if (!is_Proj(proj)) continue; switch ((pn_Div)get_Proj_num(proj)) { case pn_Div_M: /* reroute to the call */ set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_M); break; case pn_Div_X_regular: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_regular); break; case pn_Div_X_except: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_except); break; case pn_Div_res: { ir_mode *low_mode = get_irn_mode(left_low); if (arm_cg_config.big_endian) { ir_node *res_low = new_r_Proj(resproj, low_mode, res_offset+1); ir_node *res_high = new_r_Proj(resproj, mode, res_offset); ir_set_dw_lowered(proj, res_low, res_high); } else { ir_node *res_low = new_r_Proj(resproj, low_mode, res_offset); ir_node *res_high = new_r_Proj(resproj, mode, res_offset+1); ir_set_dw_lowered(proj, res_low, res_high); } break; } } /* mark this proj: we have handled it already, otherwise we might fall * into out new nodes. */ mark_irn_visited(proj); }