aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2015-05-27 18:00:15 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-05-27 18:00:15 +0000
commit8974754f6f12f2f032d4122b06d26319545ced00 (patch)
tree400932ae2cd83549d10a0b94fb453c26608f0409 /gcc/tree.c
parente590690ef23053ddbd5b32c119f403f418a02d6a (diff)
downloadgcc-8974754f6f12f2f032d4122b06d26319545ced00.zip
gcc-8974754f6f12f2f032d4122b06d26319545ced00.tar.gz
gcc-8974754f6f12f2f032d4122b06d26319545ced00.tar.bz2
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
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c137
1 files changed, 135 insertions, 2 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 60d4509..c22fa76 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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. */