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; }
ir_node *dmemory_default_get_arraylength(ir_node* objptr, ir_graph *irg, ir_node *block, ir_node **mem) { /* calculate address of arraylength field */ int length_len = get_mode_size_bytes(default_arraylength_mode); ir_node *cnst = new_r_Const_long(irg, mode_P, -length_len); ir_node *length_addr = new_r_Add(block, objptr, cnst, mode_P); ir_node *cur_mem = *mem; ir_node *load = new_r_Load(block, cur_mem, length_addr, default_arraylength_mode, cons_none); cur_mem = new_r_Proj(load, mode_M, pn_Load_M); ir_node *len = new_r_Proj(load, default_arraylength_mode, pn_Load_res); *mem = cur_mem; return len; }
/** * Turn a small CopyB node into a series of Load/Store nodes. */ static void lower_small_copyb_node(ir_node *irn) { ir_graph *irg = get_irn_irg(irn); ir_node *block = get_nodes_block(irn); ir_type *tp = get_CopyB_type(irn); ir_node *addr_src = get_CopyB_src(irn); ir_node *addr_dst = get_CopyB_dst(irn); ir_node *mem = get_CopyB_mem(irn); ir_mode *mode_ref = get_irn_mode(addr_src); unsigned mode_bytes = allow_misalignments ? native_mode_bytes : get_type_alignment_bytes(tp); unsigned size = get_type_size_bytes(tp); unsigned offset = 0; while (offset < size) { ir_mode *mode = get_ir_mode(mode_bytes); for (; offset + mode_bytes <= size; offset += mode_bytes) { ir_mode *mode_ref_int = get_reference_offset_mode(mode_ref); /* construct offset */ ir_node *addr_const = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add = new_r_Add(block, addr_src, addr_const, mode_ref); ir_node *load = new_r_Load(block, mem, add, mode, tp, cons_none); ir_node *load_res = new_r_Proj(load, mode, pn_Load_res); ir_node *load_mem = new_r_Proj(load, mode_M, pn_Load_M); ir_node *addr_const2 = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add2 = new_r_Add(block, addr_dst, addr_const2, mode_ref); ir_node *store = new_r_Store(block, load_mem, add2, load_res, tp, cons_none); ir_node *store_mem = new_r_Proj(store, mode_M, pn_Store_M); mem = store_mem; } mode_bytes /= 2; } exchange(irn, mem); }