Commit bf6b7292 by Eric Botcazou

misc.c (gnat_type_max_size): Try to return a meaningful value for array types…

misc.c (gnat_type_max_size): Try to return a meaningful value for array types with TYPE_INDEX_TYPE set on...

	* gcc-interface/misc.c (gnat_type_max_size): Try to return a meaningful
	value for array types with TYPE_INDEX_TYPE set on their domain type.
	* gcc-interface/utils.c (max_size): For operations and expressions, do
	not build a new node if the operands have not changed or are missing.

From-SVN: r245698
parent 4af362a9
......@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
* Copyright (C) 1992-2016, Free Software Foundation, Inc. *
* Copyright (C) 1992-2017, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
......@@ -736,22 +736,59 @@ gnat_type_max_size (const_tree gnu_type)
elaborated and possibly replaced by a VAR_DECL. */
tree max_unitsize = max_size (TYPE_SIZE_UNIT (gnu_type), true);
/* If we don't have a constant, see what we can get from TYPE_ADA_SIZE,
which should stay untouched. */
if (!tree_fits_uhwi_p (max_unitsize)
&& RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
&& TYPE_ADA_SIZE (gnu_type))
/* If we don't have a constant, try to look at attributes which should have
stayed untouched. */
if (!tree_fits_uhwi_p (max_unitsize))
{
tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
/* If we have succeeded in finding a constant, round it up to the
type's alignment and return the result in units. */
if (tree_fits_uhwi_p (max_adasize))
max_unitsize
= size_binop (CEIL_DIV_EXPR,
round_up (max_adasize, TYPE_ALIGN (gnu_type)),
bitsize_unit_node);
/* For record types, see what we can get from TYPE_ADA_SIZE. */
if (RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
&& TYPE_ADA_SIZE (gnu_type))
{
tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
/* If we have succeeded in finding a constant, round it up to the
type's alignment and return the result in units. */
if (tree_fits_uhwi_p (max_adasize))
max_unitsize
= size_binop (CEIL_DIV_EXPR,
round_up (max_adasize, TYPE_ALIGN (gnu_type)),
bitsize_unit_node);
}
/* For array types, see what we can get from TYPE_INDEX_TYPE. */
else if (TREE_CODE (gnu_type) == ARRAY_TYPE
&& TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))
&& tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (gnu_type))))
{
tree lb = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
tree hb = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
if (TREE_CODE (lb) != INTEGER_CST
&& TYPE_RM_SIZE (TREE_TYPE (lb))
&& compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (lb)), 16) <= 0)
lb = TYPE_MIN_VALUE (TREE_TYPE (lb));
if (TREE_CODE (hb) != INTEGER_CST
&& TYPE_RM_SIZE (TREE_TYPE (hb))
&& compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (hb)), 16) <= 0)
hb = TYPE_MAX_VALUE (TREE_TYPE (hb));
if (TREE_CODE (lb) == INTEGER_CST && TREE_CODE (hb) == INTEGER_CST)
{
tree ctype = get_base_type (TREE_TYPE (lb));
lb = fold_convert (ctype, lb);
hb = fold_convert (ctype, hb);
if (tree_int_cst_le (lb, hb))
{
tree length
= fold_build2 (PLUS_EXPR, ctype,
fold_build2 (MINUS_EXPR, ctype, hb, lb),
build_int_cst (ctype, 1));
max_unitsize
= fold_build2 (MULT_EXPR, sizetype,
fold_convert (sizetype, length),
TYPE_SIZE_UNIT (TREE_TYPE (gnu_type)));
}
}
}
}
return max_unitsize;
......
......@@ -3534,6 +3534,7 @@ max_size (tree exp, bool max_p)
{
enum tree_code code = TREE_CODE (exp);
tree type = TREE_TYPE (exp);
tree op0, op1, op2;
switch (TREE_CODE_CLASS (code))
{
......@@ -3575,15 +3576,19 @@ max_size (tree exp, bool max_p)
return exp;
case tcc_comparison:
return max_p ? size_one_node : size_zero_node;
return build_int_cst (type, max_p ? 1 : 0);
case tcc_unary:
if (code == NON_LVALUE_EXPR)
return max_size (TREE_OPERAND (exp, 0), max_p);
return fold_build1 (code, type,
max_size (TREE_OPERAND (exp, 0),
code == NEGATE_EXPR ? !max_p : max_p));
op0 = max_size (TREE_OPERAND (exp, 0),
code == NEGATE_EXPR ? !max_p : max_p);
if (op0 == TREE_OPERAND (exp, 0))
return exp;
return fold_build1 (code, type, op0);
case tcc_binary:
{
......@@ -3623,6 +3628,9 @@ max_size (tree exp, bool max_p)
code = PLUS_EXPR;
}
if (lhs == TREE_OPERAND (exp, 0) && rhs == TREE_OPERAND (exp, 1))
return exp;
/* We need to detect overflows so we call size_binop here. */
return size_binop (code, lhs, rhs);
}
......@@ -3634,23 +3642,40 @@ max_size (tree exp, bool max_p)
if (code == SAVE_EXPR)
return exp;
return fold_build1 (code, type,
max_size (TREE_OPERAND (exp, 0),
code == TRUTH_NOT_EXPR ? !max_p : max_p));
op0 = max_size (TREE_OPERAND (exp, 0),
code == TRUTH_NOT_EXPR ? !max_p : max_p);
if (op0 == TREE_OPERAND (exp, 0))
return exp;
return fold_build1 (code, type, op0);
case 2:
if (code == COMPOUND_EXPR)
return max_size (TREE_OPERAND (exp, 1), max_p);
return fold_build2 (code, type,
max_size (TREE_OPERAND (exp, 0), max_p),
max_size (TREE_OPERAND (exp, 1), max_p));
op0 = max_size (TREE_OPERAND (exp, 0), max_p);
op1 = max_size (TREE_OPERAND (exp, 1), max_p);
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
return exp;
return fold_build2 (code, type, op0, op1);
case 3:
if (code == COND_EXPR)
return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (TREE_OPERAND (exp, 1), max_p),
max_size (TREE_OPERAND (exp, 2), max_p));
{
op1 = TREE_OPERAND (exp, 1);
op2 = TREE_OPERAND (exp, 2);
if (!op1 || !op2)
return exp;
return
fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (op1, max_p), max_size (op2, max_p));
}
break;
default:
break;
......
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