ir_node *dmemory_default_alloc_array(ir_type *eltype, ir_node *count, ir_graph *irg, ir_node *block, ir_node **mem) { ir_node *cur_mem = *mem; unsigned count_size = get_mode_size_bytes(default_arraylength_mode); unsigned element_size = is_Class_type(eltype) ? get_mode_size_bytes(mode_P) : get_type_size_bytes(eltype); // FIXME: some langs support arrays of structs. /* increase element count so we have enough space for a counter at the front */ unsigned add_size = (element_size + (count_size-1)) / count_size; ir_node *count_u = new_r_Conv(block, count, mode_Iu); ir_node *addv = new_r_Const_long(irg, mode_Iu, add_size); ir_node *add1 = new_r_Add(block, count_u, addv, mode_Iu); ir_node *elsizev = new_r_Const_long(irg, mode_Iu, element_size); ir_node *size = new_r_Mul(block, add1, elsizev, mode_Iu); unsigned addr_delta = add_size * element_size; symconst_symbol calloc_sym; calloc_sym.entity_p = calloc_entity; ir_node *callee = new_r_SymConst(irg, mode_P, calloc_sym, symconst_addr_ent); ir_node *one = new_r_Const_long(irg, mode_Iu, 1); ir_node *in[2] = { one, size }; ir_type *call_type = get_entity_type(calloc_entity); ir_node *call = new_r_Call(block, cur_mem, callee, 2, in, 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_P, 0); /* write length of array */ ir_node *len_value = new_r_Conv(block, count, default_arraylength_mode); ir_node *len_delta = new_r_Const_long(irg, mode_P, (int)addr_delta-4); //FIXME: replace magic num ir_node *len_addr = new_r_Add(block, res, len_delta, mode_P); ir_node *store = new_r_Store(block, cur_mem, len_addr, len_value, cons_none); cur_mem = new_r_Proj(store, mode_M, pn_Store_M); if (addr_delta > 0) { ir_node *delta = new_r_Const_long(irg, mode_P, (int)addr_delta); res = new_r_Add(block, res, delta, mode_P); } *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; }
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 void arm_collect_frame_entity_nodes(ir_node *node, void *data) { if (!is_frame_load(node)) return; const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node); if (!attr->is_frame_entity) return; const ir_entity *entity = attr->entity; if (entity != NULL) return; be_fec_env_t *const env = (be_fec_env_t*)data; unsigned const size = get_mode_size_bytes(attr->load_store_mode); be_load_needs_frame_entity(env, node, size, log2_floor(size)); }
/** * Lower a Sel node. Do not touch Sels accessing entities on the frame type. */ static void lower_sel(ir_node *sel) { ir_graph *irg = get_irn_irg(sel); ir_entity *ent = get_Sel_entity(sel); ir_type *owner = get_entity_owner(ent); dbg_info *dbg = get_irn_dbg_info(sel); ir_mode *mode = get_irn_mode(sel); ir_node *bl = get_nodes_block(sel); ir_node *newn; /* we can only replace Sels when the layout of the owner type is decided. */ if (get_type_state(owner) != layout_fixed) return; if (0 < get_Sel_n_indexs(sel)) { /* an Array access */ ir_type *basetyp = get_entity_type(ent); ir_mode *basemode; ir_node *index; if (is_Primitive_type(basetyp)) basemode = get_type_mode(basetyp); else basemode = mode_P_data; assert(basemode && "no mode for lowering Sel"); assert((get_mode_size_bits(basemode) % 8 == 0) && "can not deal with unorthodox modes"); index = get_Sel_index(sel, 0); if (is_Array_type(owner)) { ir_type *arr_ty = owner; size_t dims = get_array_n_dimensions(arr_ty); size_t *map = ALLOCAN(size_t, dims); ir_mode *mode_Int = get_reference_mode_signed_eq(mode); ir_tarval *tv; ir_node *last_size; size_t i; assert(dims == (size_t)get_Sel_n_indexs(sel) && "array dimension must match number of indices of Sel node"); for (i = 0; i < dims; i++) { size_t order = get_array_order(arr_ty, i); assert(order < dims && "order of a dimension must be smaller than the arrays dim"); map[order] = i; } newn = get_Sel_ptr(sel); /* Size of the array element */ tv = new_tarval_from_long(get_type_size_bytes(basetyp), mode_Int); last_size = new_rd_Const(dbg, irg, tv); /* * We compute the offset part of dimension d_i recursively * with the the offset part of dimension d_{i-1} * * off_0 = sizeof(array_element_type); * off_i = (u_i - l_i) * off_{i-1} ; i >= 1 * * whereas u_i is the upper bound of the current dimension * and l_i the lower bound of the current dimension. */ for (i = dims; i > 0;) { size_t dim = map[--i]; ir_node *lb, *ub, *elms, *n, *ind; elms = NULL; lb = get_array_lower_bound(arr_ty, dim); ub = get_array_upper_bound(arr_ty, dim); if (! is_Unknown(lb)) lb = new_rd_Conv(dbg, bl, copy_const_value(get_irn_dbg_info(sel), lb, bl), mode_Int); else lb = NULL; if (! is_Unknown(ub)) ub = new_rd_Conv(dbg, bl, copy_const_value(get_irn_dbg_info(sel), ub, bl), mode_Int); else ub = NULL; /* * If the array has more than one dimension, lower and upper * bounds have to be set in the non-last dimension. */ if (i > 0) { assert(lb != NULL && "lower bound has to be set in multi-dim array"); assert(ub != NULL && "upper bound has to be set in multi-dim array"); /* Elements in one Dimension */ elms = new_rd_Sub(dbg, bl, ub, lb, mode_Int); } ind = new_rd_Conv(dbg, bl, get_Sel_index(sel, dim), mode_Int); /* * Normalize index, id lower bound is set, also assume * lower bound == 0 */ if (lb != NULL) ind = new_rd_Sub(dbg, bl, ind, lb, mode_Int); n = new_rd_Mul(dbg, bl, ind, last_size, mode_Int); /* * see comment above. */ if (i > 0) last_size = new_rd_Mul(dbg, bl, last_size, elms, mode_Int); newn = new_rd_Add(dbg, bl, newn, n, mode); } } else { /* no array type */ ir_mode *idx_mode = get_irn_mode(index); ir_tarval *tv = new_tarval_from_long(get_mode_size_bytes(basemode), idx_mode); newn = new_rd_Add(dbg, bl, get_Sel_ptr(sel), new_rd_Mul(dbg, bl, index, new_r_Const(irg, tv), idx_mode), mode); } } else if (is_Method_type(get_entity_type(ent)) && is_Class_type(owner)) { /* We need an additional load when accessing methods from a dispatch * table. * Matze TODO: Is this really still used? At least liboo does its own * lowering of Method-Sels... */ ir_mode *ent_mode = get_type_mode(get_entity_type(ent)); int offset = get_entity_offset(ent); ir_mode *mode_Int = get_reference_mode_signed_eq(mode); ir_tarval *tv = new_tarval_from_long(offset, mode_Int); ir_node *cnst = new_rd_Const(dbg, irg, tv); ir_node *add = new_rd_Add(dbg, bl, get_Sel_ptr(sel), cnst, mode); ir_node *mem = get_Sel_mem(sel); newn = new_rd_Load(dbg, bl, mem, add, ent_mode, cons_none); newn = new_r_Proj(newn, ent_mode, pn_Load_res); } else { int offset = get_entity_offset(ent); /* replace Sel by add(obj, const(ent.offset)) */ newn = get_Sel_ptr(sel); if (offset != 0) { ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode); ir_tarval *tv = new_tarval_from_long(offset, mode_UInt); ir_node *cnst = new_r_Const(irg, tv); newn = new_rd_Add(dbg, bl, newn, cnst, mode); } } /* run the hooks */ hook_lower(sel); exchange(sel, newn); }