(min_precision): New function.

(finish_enum): Rewrite code to determine precision required for enumeral type.

From-SVN: r7471
This commit is contained in:
Richard Kenner 1994-06-14 17:55:38 -04:00
parent 62c0ea12e9
commit de953b38a3

View File

@ -5621,6 +5621,37 @@ start_enum (name)
return enumtype;
}
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
static int
min_precision (value, unsignedp)
tree value;
int unsignedp;
{
int log;
/* If the value is negative, compute its negative minus 1. The latter
adjustment is because the absolute value of the largest negative value
is one larger than the largest positive value. This is equivalent to
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
value = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (value), value));
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
if (integer_zerop (value))
log = 0;
else if (TREE_INT_CST_HIGH (value) != 0)
log = HOST_BITS_PER_WIDE_INT + floor_log2 (TREE_INT_CST_HIGH (value));
else
log = floor_log2 (TREE_INT_CST_LOW (value));
return log + 1 + ! unsignedp;
}
/* After processing and defining all the values of an enumeration type,
install their decls in the enumeration type and finish it off.
ENUMTYPE is the type object and VALUES a list of decl-value pairs.
@ -5632,9 +5663,7 @@ finish_enum (enumtype, values)
{
register tree pair, tem;
tree minnode = 0, maxnode = 0;
register HOST_WIDE_INT maxvalue = 0;
register HOST_WIDE_INT minvalue = 0;
unsigned precision = 0;
int lowprec, highprec, precision;
int toplevel = global_binding_level == current_binding_level;
if (in_parm_level_p ())
@ -5662,34 +5691,14 @@ finish_enum (enumtype, values)
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_MAX_VALUE (enumtype) = maxnode;
/* An enum can have some negative values; then it is signed. */
TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
/* Determine the precision this type needs. */
if (TREE_INT_CST_HIGH (minnode) >= 0
? tree_int_cst_lt (TYPE_MAX_VALUE (unsigned_type_node), maxnode)
: (tree_int_cst_lt (minnode, TYPE_MIN_VALUE (integer_type_node))
|| tree_int_cst_lt (TYPE_MAX_VALUE (integer_type_node), maxnode)))
precision = TYPE_PRECISION (long_long_integer_type_node);
else
{
maxvalue = TREE_INT_CST_LOW (maxnode);
minvalue = TREE_INT_CST_LOW (minnode);
if (maxvalue > 0)
precision = floor_log2 (maxvalue) + 1;
if (minvalue < 0)
{
/* Compute number of bits to represent magnitude of a negative value.
Add one to MINVALUE since range of negative numbers
includes the power of two. */
unsigned negprecision = floor_log2 (-minvalue - 1) + 1;
if (negprecision > precision)
precision = negprecision;
precision += 1; /* room for sign bit */
}
if (!precision)
precision = 1;
}
lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
precision = MAX (lowprec, highprec);
if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
/* Use the width of the narrowest normal C type which is wide enough. */
@ -5700,9 +5709,6 @@ finish_enum (enumtype, values)
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
/* An enum can have some negative values; then it is signed. */
TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
if (values != error_mark_node)
{
/* Change the type of the enumerators to be the enum type.