Commit de953b38 by Richard Kenner

(min_precision): New function.

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

From-SVN: r7471
parent 62c0ea12
......@@ -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;
/* 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);
/* An enum can have some negative values; then it is signed. */
TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
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 */
}
/* Determine the precision this type needs. */
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment