예제 #1
0
파일: type.c 프로젝트: 8l/ucc-c-compiler
integral_t type_max(type *r, where *from)
{
	unsigned sz = type_size(r, from);
	unsigned bits = sz * CHAR_BIT;
	int is_signed = type_is_signed(r);

	integral_t max = ~0ULL >> (INTEGRAL_BITS - bits);

	if(is_signed)
		max = max / 2 - 1;

	return max;
}
예제 #2
0
type *decl_type_for_bitfield(decl *d)
{
	assert(!type_is(d->ref, type_func));

	if(d->bits.var.field_width){
		const unsigned bits = const_fold_val_i(d->bits.var.field_width);
		const int is_signed = type_is_signed(d->ref);
		unsigned bytes = bits / CHAR_BIT;

		/* need to add on a byte for any leftovers */
		if(bits % CHAR_BIT)
			bytes++;

		return type_nav_MAX_FOR(cc1_type_nav, bytes, is_signed);
	}else{
		return d->ref;
	}
}
예제 #3
0
static void try_shift_conv(
		out_ctx *octx,
		enum op_type *binop,
		const out_val **lhs, const out_val **rhs)
{
	if(type_is_signed((*lhs)->t))
		return;

	if(*binop == op_divide && (*rhs)->type == V_CONST_I){
		integral_t k = (*rhs)->bits.val_i;
		if((k & (k - 1)) == 0){
			/* power of two, can shift */
			out_val *mut;

			*binop = op_shiftr;

			*rhs = mut = v_dup_or_reuse(octx, *rhs, (*rhs)->t);
			mut->bits.val_i = log2(k);
		}
	}else if(*binop == op_multiply){
		const out_val **vconst = (*lhs)->type == V_CONST_I ? lhs : rhs;
		integral_t k = (*vconst)->bits.val_i;

		if((k & (k - 1)) == 0){
			out_val *mut;

			*binop = op_shiftl;

			*vconst = mut = v_dup_or_reuse(octx, *vconst, (*vconst)->t);
			mut->bits.val_i = log2(k);

			if(vconst == lhs){
				/* need to swap as shift expects the constant to be rhs */
				const out_val *tmp = *lhs;
				*lhs = *rhs;
				*rhs = tmp;
			}
		}
	}
}
예제 #4
0
void bitfield_trunc_check(decl *mem, expr *from)
{
	consty k;

	if(expr_kind(from, cast)){
		/* we'll warn about bitfield truncation, prevent warnings
		 * about cast truncation
		 */
		from->expr_cast_implicit = 0;
	}

	const_fold(from, &k);

	if(k.type == CONST_NUM){
		const sintegral_t kexp = k.bits.num.val.i;
		/* highest may be -1 - kexp is zero */
		const int highest = integral_high_bit(k.bits.num.val.i, from->tree_type);
		const int is_signed = type_is_signed(mem->bits.var.field_width->tree_type);

		const_fold(mem->bits.var.field_width, &k);

		UCC_ASSERT(k.type == CONST_NUM, "bitfield size not val?");
		UCC_ASSERT(K_INTEGRAL(k.bits.num), "fp bitfield size?");

		if(highest > (sintegral_t)k.bits.num.val.i
		|| (is_signed && highest == (sintegral_t)k.bits.num.val.i))
		{
			sintegral_t kexp_to = kexp & ~(-1UL << k.bits.num.val.i);

			cc1_warn_at(&from->where,
					bitfield_trunc,
					"truncation in store to bitfield alters value: "
					"%" NUMERIC_FMT_D " -> %" NUMERIC_FMT_D,
					kexp, kexp_to);
		}
	}
}
예제 #5
0
static integral_t convert_integral_to_integral_warn(
		const integral_t in, type *tin,
		type *tout,
		int do_warn, where *w)
{
	/*
	 * C99
	 * 6.3.1.3 Signed and unsigned integers
	 *
	 * When a value with integer type is converted to another integer type
	 * other than _Bool, if the value can be represented by the new type, it
	 * is unchanged.
	 *
	 * Otherwise, if the new type is unsigned, the value is converted by
	 * repeatedly adding or subtracting one more than the maximum value that
	 * can be represented in the new type until the value is in the range of
	 * the new type.
	 *
	 * Otherwise, the new type is signed and the value cannot be represented
	 * in it; either the result is implementation-defined or an
	 * implementation-defined signal is raised.
	 */

	/* representable
	 * if size(out) > size(in)
	 * or if size(out) == size(in)
	 *    and conversion is not unsigned -> signed
	 * or conversion is unsigned -> signed and in < signed-max
	 */

	const unsigned sz_out = type_size(tout, w);
	const int signed_in = type_is_signed(tin);
	const int signed_out = type_is_signed(tout);
	sintegral_t to_iv_sign_ext;
	integral_t to_iv = integral_truncate(in, sz_out, &to_iv_sign_ext);
	integral_t ret;

	if(!signed_out && signed_in){
		const unsigned sz_in_bits = CHAR_BIT * type_size(tin, w);
		const unsigned sz_out_bits = CHAR_BIT * sz_out;

		/* e.g. "(unsigned)-1". Pick to_iv, i.e. the unsigned truncated repr
		 * this assumes that signed ints on the host machine we're run on
		 * are 2's complement, i.e. truncated a negative gives us all 1s,
		 * which we truncate */
		ret = to_iv;

		/* need to ensure sign extension */
		if(ret & (1ULL << (sz_in_bits - 1))
		&& sz_in_bits != sz_out_bits)
		{
			ret |= -1ULL << sz_in_bits;

			/* need to unmask any top bits, e.g. int instead of long long */
			if(sz_out_bits >= CHAR_BIT * sizeof(ret)){
				/* shift would be a no-op (technically UB) */
			}else{
				ret &= -1ULL >> sz_out_bits;
			}
		}

	}else if(signed_in){