Beispiel #1
0
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,
	};
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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);
}
Beispiel #10
0
/**
 * @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);
}
Beispiel #11
0
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);
	}