コード例 #1
0
ファイル: analyze_irg_args.c プロジェクト: lu-zero/libfirm
/**
 * Check if a argument of the ir graph with mode
 * reference is read, write or both.
 *
 * @param irg   The ir graph to analyze.
 */
static void analyze_ent_args(ir_entity *ent)
{
	ir_type *mtp     = get_entity_type(ent);
	size_t   nparams = get_method_n_params(mtp);

	ent->attr.mtd_attr.param_access = NEW_ARR_F(ptr_access_kind, nparams);

	/* If the method haven't parameters we have
	 * nothing to do.
	 */
	if (nparams <= 0)
		return;

  /* we have not yet analyzed the graph, set ALL access for pointer args */
	for (size_t i = nparams; i-- > 0; ) {
		ir_type *type = get_method_param_type(mtp, i);
		ent->attr.mtd_attr.param_access[i] = is_Pointer_type(type) ? ptr_access_all : ptr_access_none;
	}

	ir_graph *irg = get_entity_irg(ent);
	if (irg == NULL) {
		/* no graph, no better info */
		return;
	}

	assure_irg_outs(irg);
	ir_node *irg_args = get_irg_args(irg);

	/* A array to save the information for each argument with
	   mode reference.*/
	ptr_access_kind *rw_info;
	NEW_ARR_A(ptr_access_kind, rw_info, nparams);

	/* We initialize the element with none state. */
	for (size_t i = nparams; i-- > 0; )
		rw_info[i] = ptr_access_none;

	/* search for arguments with mode reference
	   to analyze them.*/
	for (int i = get_irn_n_outs(irg_args); i-- > 0; ) {
		ir_node *arg      = get_irn_out(irg_args, i);
		ir_mode *arg_mode = get_irn_mode(arg);
		long     proj_nr  = get_Proj_proj(arg);

		if (mode_is_reference(arg_mode))
			rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]);
	}

	/* copy the temporary info */
	memcpy(ent->attr.mtd_attr.param_access, rw_info,
	       nparams * sizeof(ent->attr.mtd_attr.param_access[0]));
}
コード例 #2
0
ファイル: amd64_emitter.c プロジェクト: qznc/libfirm
static void amd64_emit_mode_suffix(const ir_mode *mode)
{
	assert(mode_is_int(mode) || mode_is_reference(mode));
	char c;
	switch (get_mode_size_bits(mode)) {
	case 8:  c = 'b'; break;
	case 16: c = 'w'; break;
	case 32: c = 'l'; break;
	case 64: c = 'q'; break;
	default:
		panic("Can't output mode_suffix for %+F", mode);
	}
	be_emit_char(c);
}
コード例 #3
0
ファイル: opt_confirms.c プロジェクト: qznc/libfirm
/*
 * Check, if the value of a node cannot represent a NULL pointer.
 *
 * - Sels are skipped
 * - A SymConst(entity) is NEVER a NULL pointer
 * - Confirms are evaluated
 */
int value_not_null(const ir_node *n, const ir_node **confirm)
{
	ir_tarval *tv;

	*confirm = NULL;

	tv = value_of(n);
	if (tarval_is_constant(tv) && ! tarval_is_null(tv))
		return 1;

	assert(mode_is_reference(get_irn_mode(n)));
	/* skip all Sel nodes */
	while (is_Sel(n)) {
		n = get_Sel_ptr(n);
	}
	while (1) {
		if (is_Proj(n)) { n = get_Proj_pred(n); continue; }
		break;
	}

	if (is_SymConst_addr_ent(n)) {
		/* global references are never NULL */
		return 1;
	} else if (n == get_irg_frame(get_irn_irg(n))) {
		/* local references are never NULL */
		return 1;
	} else if (is_Alloc(n)) {
		/* alloc never returns NULL (it throws an exception instead) */
		return 1;
	} else {
		/* check for more Confirms */
		for (; is_Confirm(n); n = get_Confirm_value(n)) {
			if (get_Confirm_relation(n) == ir_relation_less_greater) {
				ir_node   *bound = get_Confirm_bound(n);
				ir_tarval *tv    = value_of(bound);

				if (tarval_is_null(tv)) {
					*confirm = n;
					return 1;
				}
			}
		}
	}
	return 0;
}
コード例 #4
0
ファイル: sparc_cconv.c プロジェクト: lamproae/libfirm
calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
                                                      ir_graph *irg)
{
	bool omit_fp = false;
	if (irg != NULL) {
		omit_fp = be_options.omit_fp;
		/* our current vaarg handling needs the standard space to store the
		 * args 0-5 in it */
		if (is_method_variadic(function_type))
			omit_fp = false;
		/* The pointer to the aggregate return value belongs to the 92 magic bytes.
		 * Thus, if the called functions increases the stack size,
		 * it must copy the value to the appropriate location.
		 * This is not implemented yet, so we forbid to omit the frame pointer.
		 */
		if (get_method_calling_convention(function_type) & cc_compound_ret)
			omit_fp = false;
		if (omit_fp)
			irg_walk_graph(irg, check_omit_fp, NULL, &omit_fp);
		sparc_get_irg_data(irg)->omit_fp = omit_fp;
	}

	mtp_additional_properties mtp
		= get_method_additional_properties(function_type);
	unsigned *caller_saves = rbitset_malloc(N_SPARC_REGISTERS);
	if (mtp & mtp_property_returns_twice) {
		rbitset_copy(caller_saves, default_returns_twice_saves,
		             N_SPARC_REGISTERS);
	} else {
		rbitset_copy(caller_saves, default_caller_saves, N_SPARC_REGISTERS);
	}

	/* determine how parameters are passed */
	int                 n_params = get_method_n_params(function_type);
	int                 regnum   = 0;
	reg_or_stackslot_t *params   = XMALLOCNZ(reg_or_stackslot_t, n_params);

	int      n_param_regs = ARRAY_SIZE(param_regs);
	unsigned stack_offset = !omit_fp ? SPARC_MIN_STACKSIZE : 0;
	for (int i = 0; i < n_params; ++i) {
		ir_type            *param_type = get_method_param_type(function_type,i);
		ir_mode            *mode;
		int                 bits;
		reg_or_stackslot_t *param;

		if (is_compound_type(param_type))
			panic("compound arguments not supported yet");

		mode  = get_type_mode(param_type);
		bits  = get_mode_size_bits(mode);
		param = &params[i];

		if (i == 0 &&
		    (get_method_calling_convention(function_type) & cc_compound_ret)) {
			assert(mode_is_reference(mode) && bits == 32);
			/* special case, we have reserved space for this on the between
			 * type */
			param->type   = param_type;
			param->offset = SPARC_AGGREGATE_RETURN_OFFSET;
			param->already_stored = true;
			continue;
		}

		if (regnum < n_param_regs) {
			param->offset = SPARC_PARAMS_SPILL_OFFSET
			                + regnum * SPARC_REGISTER_SIZE;
			param->type   = param_type;
			arch_register_t const *reg = param_regs[regnum++];
			if (irg == NULL || omit_fp)
				reg = map_i_to_o_reg(reg);
			param->reg0 = reg;
			param->req0 = reg->single_req;
		} else {
			param->type   = param_type;
			param->offset = stack_offset;
			param->already_stored = true;
			/* increase offset by at least SPARC_REGISTER_SIZE bytes so
			 * everything is aligned */
			stack_offset += MAX(bits / 8, SPARC_REGISTER_SIZE);
			continue;
		}

		/* we might need a 2nd 32bit component (for 64bit or double values) */
		if (bits > 32) {
			if (bits > 64)
				panic("only 32 and 64bit modes supported");

			if (regnum < n_param_regs) {
				param->offset = SPARC_PARAMS_SPILL_OFFSET
				                + regnum * SPARC_REGISTER_SIZE;
				arch_register_t const *reg = param_regs[regnum++];
				if (irg == NULL || omit_fp)
					reg = map_i_to_o_reg(reg);
				param->reg1 = reg;
				param->req1 = reg->single_req;
			} else {
				ir_mode *regmode = param_regs[0]->cls->mode;
				ir_type *type    = get_type_for_mode(regmode);
				param->type      = type;
				param->offset    = stack_offset;
				assert(get_mode_size_bits(regmode) == 32);
				stack_offset += SPARC_REGISTER_SIZE;
			}
		}
	}
	unsigned n_param_regs_used = regnum;

	/* determine how results are passed */
	int                 n_results           = get_method_n_ress(function_type);
	unsigned            float_regnum        = 0;
	unsigned            n_reg_results       = 0;
	unsigned            n_float_result_regs = ARRAY_SIZE(float_result_regs);
	reg_or_stackslot_t *results = XMALLOCNZ(reg_or_stackslot_t, n_results);
	regnum        = 0;
	for (int i = 0; i < n_results; ++i) {
		ir_type            *result_type = get_method_res_type(function_type, i);
		ir_mode            *result_mode = get_type_mode(result_type);
		reg_or_stackslot_t *result      = &results[i];

		if (mode_is_float(result_mode)) {
			unsigned n_regs   = determine_n_float_regs(result_mode);
			unsigned next_reg = round_up2(float_regnum, n_regs);

			if (next_reg >= n_float_result_regs) {
				panic("too many float results");
			} else {
				const arch_register_t *reg = float_result_regs[next_reg];
				rbitset_clear(caller_saves, reg->global_index);
				if (n_regs == 1) {
					result->req0 = reg->single_req;
				} else if (n_regs == 2) {
					result->req0 = &float_result_reqs_double[next_reg];
					rbitset_clear(caller_saves, reg->global_index+1);
				} else if (n_regs == 4) {
					result->req0 = &float_result_reqs_quad[next_reg];
					rbitset_clear(caller_saves, reg->global_index+1);
					rbitset_clear(caller_saves, reg->global_index+2);
					rbitset_clear(caller_saves, reg->global_index+3);
				} else {
					panic("invalid number of registers in result");
				}
				float_regnum = next_reg + n_regs;

				++n_reg_results;
			}
		} else {
			if (get_mode_size_bits(result_mode) > 32) {
				panic("results with more than 32bits not supported yet");
			}

			if (regnum >= n_param_regs) {
				panic("too many results");
			} else {
				const arch_register_t *reg = param_regs[regnum++];
				if (irg == NULL || omit_fp)
					reg = map_i_to_o_reg(reg);
				result->req0 = reg->single_req;
				rbitset_clear(caller_saves, reg->global_index);
				++n_reg_results;
			}
		}
	}

	calling_convention_t *cconv = XMALLOCZ(calling_convention_t);
	cconv->n_parameters     = n_params;
	cconv->parameters       = params;
	cconv->param_stack_size = stack_offset - SPARC_MIN_STACKSIZE;
	cconv->n_param_regs     = n_param_regs_used;
	cconv->results          = results;
	cconv->omit_fp          = omit_fp;
	cconv->caller_saves     = caller_saves;
	cconv->n_reg_results    = n_reg_results;

	/* setup ignore register array */
	if (irg != NULL) {
		be_irg_t *birg = be_birg_from_irg(irg);

		birg->allocatable_regs = be_cconv_alloc_all_regs(&birg->obst, N_SPARC_REGISTERS);
		be_cconv_rem_regs(birg->allocatable_regs, ignore_regs, ARRAY_SIZE(ignore_regs));
	}

	return cconv;
}
コード例 #5
0
ファイル: opt_confirms.c プロジェクト: qznc/libfirm
/**
 * Return the value of a Cmp if one or both predecessors
 * are Confirm nodes.
 *
 * @param cmp      the Cmp node
 * @param left     the left operand of the Cmp
 * @param right    the right operand of the Cmp
 * @param relation the compare relation
 */
ir_tarval *computed_value_Cmp_Confirm(const ir_node *cmp, ir_node *left, ir_node *right, ir_relation relation)
{
	ir_node    *l_bound;
	ir_relation l_relation, res_relation, neg_relation;
	interval_t  l_iv, r_iv;
	ir_tarval  *tv;

	if (is_Confirm(right)) {
		/* we want the Confirm on the left side */
		ir_node *t = right;
		right = left;
		left  = t;

		relation = get_inversed_relation(relation);
	} else if (! is_Confirm(left)) {
		/* nothing more found */
		tv = tarval_bad;
		goto check_null_case;
	}

	/* ok, here at least left is a Confirm, right might be */
	l_bound    = get_Confirm_bound(left);
	l_relation = get_Confirm_relation(left);

	if (is_Confirm(right)) {
		/*
		 * both sides are Confirm's. Check some rare cases first.
		 */
		ir_node    *r_bound    = get_Confirm_bound(right);
		ir_relation r_relation = get_Confirm_relation(right);

		/*
		 * some check can be made WITHOUT constant bounds
		 */
		if (r_bound == l_bound) {
			if (is_transitive(l_relation)) {
				ir_relation r_inc_relation = get_inversed_relation(r_relation);

				/*
				 * triangle inequality:
				 *
				 * a CMP B && B CMP b => a CMP b, !(a ~CMP b)
				 *
				 * We handle correctly cases with some <=/>= here
				 */
				if ((l_relation & ~ir_relation_equal) == (r_inc_relation & ~ir_relation_equal)) {
					res_relation = (l_relation & ~ir_relation_equal) | (l_relation & r_inc_relation & ir_relation_equal);

					if ((relation == res_relation) || ((relation & ~ir_relation_equal) == res_relation)) {
						DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, "true");
						DBG_EVAL_CONFIRM(cmp);
						return tarval_b_true;
					} else {
						ir_relation neg_relation = get_negated_relation(relation);

						if ((neg_relation == res_relation) || ((neg_relation & ~ir_relation_equal) == res_relation)) {
							DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, "false");
							DBG_EVAL_CONFIRM(cmp);
							return tarval_b_false;
						}
					}
				}
			}
		}

		/*
		 * Here, we check only the right Confirm, as the left Confirms are
		 * checked later anyway.
		 */
		if (left == r_bound) {
			/*
			 * l == bound(r) AND relation(r) == relation:
			 *
			 * We know that a CMP b and check for that
			 */
			if ((r_relation == relation) || (r_relation == (relation & ~ir_relation_equal))) {
				DBG_OUT_R(r_relation, r_bound, left, relation, right, "true");
				DBG_EVAL_CONFIRM(cmp);
				return tarval_b_true;
			}
			/*
			 * l == bound(r) AND relation(r) != relation:
			 *
			 * We know that a CMP b and check for a ~CMP b
			 */
			else {
				neg_relation = get_negated_relation(relation);

				if ((r_relation == neg_relation) || (r_relation == (neg_relation & ~ir_relation_equal))) {
					DBG_OUT_R(r_relation, r_bound, left, relation, right, "false");
					DBG_EVAL_CONFIRM(cmp);
					return tarval_b_false;
				}
			}
		}

		/* now, try interval magic */
		tv = compare_iv(
			get_interval(&l_iv, l_bound, l_relation),
			get_interval(&r_iv, r_bound, r_relation),
			relation);

		if (tv != tarval_bad) {
			DBG_EVAL_CONFIRM(cmp);
			return tv;
		}
	}

	/* from Here, check only left Confirm */

	/*
	 * some checks can be made WITHOUT constant bounds
	 */
	if (right == l_bound) {
		/*
		 * r == bound(l) AND relation(l) == relation:
		 *
		 * We know that a CMP b and check for that
		 */
		if ((l_relation == relation) || (l_relation == (relation & ~ir_relation_equal))) {
			DBG_OUT_L(l_relation, l_bound, left, relation, right, "true");
			DBG_EVAL_CONFIRM(cmp);
			return tarval_b_true;
		}
		/*
		 * r == bound(l) AND relation(l) is Not(relation):
		 *
		 * We know that a CMP b and check for a ~CMP b
		 */
		else {
			neg_relation = get_negated_relation(relation);

			if ((l_relation == neg_relation) || (l_relation == (neg_relation & ~ir_relation_equal))) {
				DBG_OUT_L(l_relation, l_bound, left, relation, right, "false");
				DBG_EVAL_CONFIRM(cmp);
				return tarval_b_false;
			}
		}
	}

	/* now, only right == Const can help */
	tv = value_of(right);

	if (tv != tarval_bad) {
		tv = compare_iv(
			get_interval(&l_iv, l_bound, l_relation),
			get_interval_from_tv(&r_iv, tv),
			relation);
	} else {
check_null_case:
		/* check some other cases */
		if ((relation == ir_relation_equal || relation == ir_relation_less_greater) &&
			is_Const(right) && is_Const_null(right)) {
			/* for == 0 or != 0 we have some special tools */
			ir_mode       *mode = get_irn_mode(left);
			const ir_node *dummy;
			if (mode_is_reference(mode)) {
				if (value_not_null(left, &dummy)) {
					tv = relation == ir_relation_equal ? tarval_b_false : tarval_b_true;
				}
			} else {
				if (value_not_zero(left, &dummy)) {
					tv = relation == ir_relation_equal ? tarval_b_false : tarval_b_true;
				}
			}
		}
	}

	if (tv != tarval_bad)
		DBG_EVAL_CONFIRM(cmp);

	return tv;
}
コード例 #6
0
ファイル: irmode.c プロジェクト: davidgiven/libfirm
void set_reference_mode_unsigned_eq(ir_mode *ref_mode, ir_mode *int_mode)
{
    assert(mode_is_reference(ref_mode));
    assert(mode_is_int(int_mode));
    ref_mode->eq_unsigned = int_mode;
}
コード例 #7
0
ファイル: irmode.c プロジェクト: davidgiven/libfirm
ir_mode *get_reference_mode_unsigned_eq(const ir_mode *mode)
{
    assert(mode_is_reference(mode));
    return mode->eq_unsigned;
}
コード例 #8
0
ファイル: irmode.c プロジェクト: davidgiven/libfirm
void set_modeP(ir_mode *p)
{
    assert(mode_is_reference(p));
    mode_P = p;
}
コード例 #9
0
ファイル: analyze_irg_args.c プロジェクト: lu-zero/libfirm
/**
 * Walk recursive the successors of a graph argument
 * with mode reference and mark if it will be read,
 * written or stored.
 *
 * @param arg   The graph argument with mode reference,
 *             that must be checked.
 */
static ptr_access_kind analyze_arg(ir_node *arg, ptr_access_kind bits)
{
	/* We must visit a node once to avoid endless recursion.*/
	mark_irn_visited(arg);

	for (int i = get_irn_n_outs(arg); i-- > 0; ) {
		ir_node *succ = get_irn_out(arg, i);
		if (irn_visited(succ))
			continue;

		/* We should not walk over the memory edge.*/
		if (get_irn_mode(succ) == mode_M)
			continue;

		/* If we reach with the recursion a Call node and our reference
		   isn't the address of this Call we accept that the reference will
		   be read and written if the graph of the method represented by
		   "Call" isn't computed else we analyze that graph. If our
		   reference is the address of this
		   Call node that mean the reference will be read.*/
		switch (get_irn_opcode(succ)) {

		case iro_Call: {
			ir_node *ptr  = get_Call_ptr(succ);

			if (ptr == arg) {
				/* Hmm: not sure what this is, most likely a read */
				bits |= ptr_access_read;
			} else {
				ir_entity *meth_ent;

				if (is_SymConst_addr_ent(ptr)) {
					meth_ent = get_SymConst_entity(ptr);

					for (int p = get_Call_n_params(succ); p-- > 0; ) {
						if (get_Call_param(succ, p) == arg) {
							/* an arg can be used more than once ! */
							bits |= get_method_param_access(meth_ent, p);
						}
					}
				} else if (is_Sel(ptr) && get_irp_callee_info_state() == irg_callee_info_consistent) {
					/* is be a polymorphic call but callee information is available */
					size_t n_params = get_Call_n_params(succ);

					/* simply look into ALL possible callees */
					for (int c = get_Call_n_callees(succ); c-- > 0; ) {
						meth_ent = get_Call_callee(succ, c);

						/* unknown_entity is used to signal that we don't know what is called */
						if (is_unknown_entity(meth_ent)) {
							bits |= ptr_access_all;
							break;
						}

						for (size_t p = n_params; p-- > 0; ) {
							if (get_Call_param(succ, p) == arg) {
								/* an arg can be used more than once ! */
								bits |= get_method_param_access(meth_ent, p);
							}
						}
					}
				} else /* can do anything */
					bits |= ptr_access_all;
			}

			/* search stops here anyway */
			continue;
		}
		case iro_Store:
			/* We have reached a Store node => the reference is written or stored. */
			if (get_Store_ptr(succ) == arg) {
				/* written to */
				bits |= ptr_access_write;
			} else {
				/* stored itself */
				bits |= ptr_access_store;
			}

			/* search stops here anyway */
			continue;

		case iro_Load:
			/* We have reached a Load node => the reference is read. */
			bits |= ptr_access_read;

			/* search stops here anyway */
			continue;

		case iro_Conv:
			/* our address is casted into something unknown. Break our search. */
			bits = ptr_access_all;
			break;

		default:
			break;
		}

		/* If we know that, the argument will be read, write and stored, we
		   can break the recursion.*/
		if (bits == ptr_access_all) {
			bits = ptr_access_all;
			break;
		}

		/*
		 * A calculation that do not lead to a reference mode ends our search.
		 * This is dangerous: It would allow to cast into integer and that cast back ...
		 * so, when we detect a Conv we go mad, see the Conv case above.
		 */
		if (!mode_is_reference(get_irn_mode(succ)))
			continue;

		/* follow further the address calculation */
		bits = analyze_arg(succ, bits);
	}
	set_irn_link(arg, NULL);
	return bits;
}
コード例 #10
0
ファイル: irmode.c プロジェクト: qznc/libfirm
ir_mode *get_reference_mode_signed_eq(ir_mode *mode)
{
    assert(mode_is_reference(mode));
    return mode->eq_signed;
}
コード例 #11
0
ファイル: irmode.c プロジェクト: qznc/libfirm
void set_modeP_code(ir_mode *p)
{
    assert(mode_is_reference(p));
    mode_P_code = p;
}