expr.h (array_at_struct_end_p): Move to...

* expr.h (array_at_struct_end_p): Move to...
	(array_ref_element_size): Likewise.
	(component_ref_field_offset): Likewise.
	* tree.h (array_ref_element_size): ...here.
	(array_at_struct_end_p): Likewise.
	(component_ref_field_offset): Likewise.
	* expr.c (array_ref_element_size): Move to...
	(array_ref_low_bound): Likewise.
	(array_at_struct_end_p): Likewise.
	(array_ref_up_bound): Likewise.
	(component_ref_field_offset): Likewise.
	* tree.c (array_ref_element_size): ...here.
	(array_ref_low_bound): Likewise.
	(array_ref_up_bound): Likewise.
	(array_at_struct_end_p): Likewise.
	(component_ref_field_offset): Likewise.

From-SVN: r223768
This commit is contained in:
Eric Botcazou 2015-05-27 18:00:15 +00:00 committed by Eric Botcazou
parent e590690ef2
commit 8974754f6f
5 changed files with 182 additions and 155 deletions

View File

@ -1,3 +1,22 @@
2015-05-27 Eric Botcazou <ebotcazou@adacore.com>
* expr.h (array_at_struct_end_p): Move to...
(array_ref_element_size): Likewise.
(component_ref_field_offset): Likewise.
* tree.h (array_ref_element_size): ...here.
(array_at_struct_end_p): Likewise.
(component_ref_field_offset): Likewise.
* expr.c (array_ref_element_size): Move to...
(array_ref_low_bound): Likewise.
(array_at_struct_end_p): Likewise.
(array_ref_up_bound): Likewise.
(component_ref_field_offset): Likewise.
* tree.c (array_ref_element_size): ...here.
(array_ref_low_bound): Likewise.
(array_ref_up_bound): Likewise.
(array_at_struct_end_p): Likewise.
(component_ref_field_offset): Likewise.
2015-05-27 Gregor Richards <gregor.richards@uwaterloo.ca>
Szabolcs Nagy <szabolcs.nagy@arm.com>

View File

@ -7025,139 +7025,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
return exp;
}
/* Return a tree of sizetype representing the size, in bytes, of the element
of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_element_size (tree exp)
{
tree aligned_size = TREE_OPERAND (exp, 3);
tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
location_t loc = EXPR_LOCATION (exp);
/* If a size was specified in the ARRAY_REF, it's the size measured
in alignment units of the element type. So multiply by that value. */
if (aligned_size)
{
/* ??? tree_ssa_useless_type_conversion will eliminate casts to
sizetype from another type of the same width and signedness. */
if (TREE_TYPE (aligned_size) != sizetype)
aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
return size_binop_loc (loc, MULT_EXPR, aligned_size,
size_int (TYPE_ALIGN_UNIT (elmt_type)));
}
/* Otherwise, take the size from that of the element type. Substitute
any PLACEHOLDER_EXPR that we have. */
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
}
/* Return a tree representing the lower bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_low_bound (tree exp)
{
tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
/* If a lower bound is specified in EXP, use it. */
if (TREE_OPERAND (exp, 2))
return TREE_OPERAND (exp, 2);
/* Otherwise, if there is a domain type and it has a lower bound, use it,
substituting for a PLACEHOLDER_EXPR as needed. */
if (domain_type && TYPE_MIN_VALUE (domain_type))
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
/* Otherwise, return a zero of the appropriate type. */
return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
}
/* Returns true if REF is an array reference to an array at the end of
a structure. If this is the case, the array may be allocated larger
than its upper bound implies. */
bool
array_at_struct_end_p (tree ref)
{
if (TREE_CODE (ref) != ARRAY_REF
&& TREE_CODE (ref) != ARRAY_RANGE_REF)
return false;
while (handled_component_p (ref))
{
/* If the reference chain contains a component reference to a
non-union type and there follows another field the reference
is not at the end of a structure. */
if (TREE_CODE (ref) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
{
tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
while (nextf && TREE_CODE (nextf) != FIELD_DECL)
nextf = DECL_CHAIN (nextf);
if (nextf)
return false;
}
ref = TREE_OPERAND (ref, 0);
}
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. */
if (DECL_P (ref))
return false;
return true;
}
/* Return a tree representing the upper bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_up_bound (tree exp)
{
tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
/* If there is a domain type and it has an upper bound, use it, substituting
for a PLACEHOLDER_EXPR as needed. */
if (domain_type && TYPE_MAX_VALUE (domain_type))
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
/* Otherwise fail. */
return NULL_TREE;
}
/* Return a tree representing the offset, in bytes, of the field referenced
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
tree
component_ref_field_offset (tree exp)
{
tree aligned_offset = TREE_OPERAND (exp, 2);
tree field = TREE_OPERAND (exp, 1);
location_t loc = EXPR_LOCATION (exp);
/* If an offset was specified in the COMPONENT_REF, it's the offset measured
in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that
value. */
if (aligned_offset)
{
/* ??? tree_ssa_useless_type_conversion will eliminate casts to
sizetype from another type of the same width and signedness. */
if (TREE_TYPE (aligned_offset) != sizetype)
aligned_offset = fold_convert_loc (loc, sizetype, aligned_offset);
return size_binop_loc (loc, MULT_EXPR, aligned_offset,
size_int (DECL_OFFSET_ALIGN (field)
/ BITS_PER_UNIT));
}
/* Otherwise, take the offset from that of the field. Substitute
any PLACEHOLDER_EXPR that we have. */
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
}
/* Alignment in bits the TARGET of an assignment may be assumed to have. */
static unsigned HOST_WIDE_INT

View File

@ -281,19 +281,10 @@ rtx get_personality_function (tree);
extern int can_move_by_pieces (unsigned HOST_WIDE_INT, unsigned int);
extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
bool array_at_struct_end_p (tree);
/* Return a tree of sizetype representing the size, in bytes, of the element
of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_element_size (tree);
extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *,
HOST_WIDE_INT *, bool *);
/* Return a tree representing the offset, in bytes, of the field referenced
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
extern tree component_ref_field_offset (tree);
extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
enum expand_modifier);

View File

@ -24,8 +24,8 @@ along with GCC; see the file COPYING3. If not see
tables index by tree code that describe how to take apart
nodes of that code.
It is intended to be language-independent, but occasionally
calls language-dependent routines defined (for C) in typecheck.c. */
It is intended to be language-independent but can occasionally
calls language-dependent routines. */
#include "config.h"
#include "system.h"
@ -12453,6 +12453,139 @@ get_base_address (tree t)
return t;
}
/* Return a tree of sizetype representing the size, in bytes, of the element
of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_element_size (tree exp)
{
tree aligned_size = TREE_OPERAND (exp, 3);
tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
location_t loc = EXPR_LOCATION (exp);
/* If a size was specified in the ARRAY_REF, it's the size measured
in alignment units of the element type. So multiply by that value. */
if (aligned_size)
{
/* ??? tree_ssa_useless_type_conversion will eliminate casts to
sizetype from another type of the same width and signedness. */
if (TREE_TYPE (aligned_size) != sizetype)
aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
return size_binop_loc (loc, MULT_EXPR, aligned_size,
size_int (TYPE_ALIGN_UNIT (elmt_type)));
}
/* Otherwise, take the size from that of the element type. Substitute
any PLACEHOLDER_EXPR that we have. */
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
}
/* Return a tree representing the lower bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_low_bound (tree exp)
{
tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
/* If a lower bound is specified in EXP, use it. */
if (TREE_OPERAND (exp, 2))
return TREE_OPERAND (exp, 2);
/* Otherwise, if there is a domain type and it has a lower bound, use it,
substituting for a PLACEHOLDER_EXPR as needed. */
if (domain_type && TYPE_MIN_VALUE (domain_type))
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
/* Otherwise, return a zero of the appropriate type. */
return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
}
/* Return a tree representing the upper bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
tree
array_ref_up_bound (tree exp)
{
tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
/* If there is a domain type and it has an upper bound, use it, substituting
for a PLACEHOLDER_EXPR as needed. */
if (domain_type && TYPE_MAX_VALUE (domain_type))
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
/* Otherwise fail. */
return NULL_TREE;
}
/* Returns true if REF is an array reference to an array at the end of
a structure. If this is the case, the array may be allocated larger
than its upper bound implies. */
bool
array_at_struct_end_p (tree ref)
{
if (TREE_CODE (ref) != ARRAY_REF
&& TREE_CODE (ref) != ARRAY_RANGE_REF)
return false;
while (handled_component_p (ref))
{
/* If the reference chain contains a component reference to a
non-union type and there follows another field the reference
is not at the end of a structure. */
if (TREE_CODE (ref) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
{
tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
while (nextf && TREE_CODE (nextf) != FIELD_DECL)
nextf = DECL_CHAIN (nextf);
if (nextf)
return false;
}
ref = TREE_OPERAND (ref, 0);
}
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. */
if (DECL_P (ref))
return false;
return true;
}
/* Return a tree representing the offset, in bytes, of the field referenced
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
tree
component_ref_field_offset (tree exp)
{
tree aligned_offset = TREE_OPERAND (exp, 2);
tree field = TREE_OPERAND (exp, 1);
location_t loc = EXPR_LOCATION (exp);
/* If an offset was specified in the COMPONENT_REF, it's the offset measured
in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that
value. */
if (aligned_offset)
{
/* ??? tree_ssa_useless_type_conversion will eliminate casts to
sizetype from another type of the same width and signedness. */
if (TREE_TYPE (aligned_offset) != sizetype)
aligned_offset = fold_convert_loc (loc, sizetype, aligned_offset);
return size_binop_loc (loc, MULT_EXPR, aligned_offset,
size_int (DECL_OFFSET_ALIGN (field)
/ BITS_PER_UNIT));
}
/* Otherwise, take the offset from that of the field. Substitute
any PLACEHOLDER_EXPR that we have. */
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
}
/* Return the machine mode of T. For vectors, returns the mode of the
inner type. The main use case is to feed the result to HONOR_NANS,
avoiding the BLKmode that a direct TYPE_MODE (T) might return. */

View File

@ -4564,8 +4564,34 @@ extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
#define walk_tree_without_duplicates(a,b,c) \
walk_tree_without_duplicates_1 (a, b, c, NULL)
extern tree get_base_address (tree t);
extern tree drop_tree_overflow (tree);
/* Given a memory reference expression T, return its base address.
The base address of a memory reference expression is the main
object being referenced. */
extern tree get_base_address (tree t);
/* Return a tree of sizetype representing the size, in bytes, of the element
of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_element_size (tree);
/* Return a tree representing the upper bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_up_bound (tree);
/* Return a tree representing the lower bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_low_bound (tree);
/* Returns true if REF is an array reference to an array at the end of
a structure. If this is the case, the array may be allocated larger
than its upper bound implies. */
extern bool array_at_struct_end_p (tree);
/* Return a tree representing the offset, in bytes, of the field referenced
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
extern tree component_ref_field_offset (tree);
extern int tree_map_base_eq (const void *, const void *);
extern unsigned int tree_map_base_hash (const void *);
extern int tree_map_base_marked_p (const void *);
@ -5052,12 +5078,6 @@ tree_int_cst_compare (const_tree t1, const_tree t2)
extern void set_decl_rtl (tree, rtx);
extern bool complete_ctor_at_level_p (const_tree, HOST_WIDE_INT, const_tree);
/* Return a tree representing the upper bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_up_bound (tree);
extern tree build_personality_function (const char *);
/* Given an expression EXP that is a handled_component_p,
look for the ultimate containing object, which is returned and specify
the access position and size. */
@ -5065,10 +5085,7 @@ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
tree *, machine_mode *, int *, int *,
bool);
/* Return a tree representing the lower bound of the array mentioned in
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_low_bound (tree);
extern tree build_personality_function (const char *);
struct GTY(()) int_n_trees_t {
/* These parts are initialized at runtime */