aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/misc.c
diff options
context:
space:
mode:
authorOlivier Hainque <hainque@adacore.com>2006-06-23 16:18:49 +0000
committerOlivier Hainque <hainque@gcc.gnu.org>2006-06-23 16:18:49 +0000
commita441447f7f6495bb8a8e6d160d7c095da787e708 (patch)
tree21e2dd58058f99241fdf55ad680c1c3ebc3dd2e5 /gcc/ada/misc.c
parenta3d536f1c1c0aa3d414c17c4acc44c900b1f1e38 (diff)
downloadgcc-a441447f7f6495bb8a8e6d160d7c095da787e708.zip
gcc-a441447f7f6495bb8a8e6d160d7c095da787e708.tar.gz
gcc-a441447f7f6495bb8a8e6d160d7c095da787e708.tar.bz2
tree.c (max_int_size_in_bytes): New function, inspired from code in function.c:assign_temp.
* tree.c (max_int_size_in_bytes): New function, inspired from code in function.c:assign_temp. * tree.h (max_int_size_in_bytes): Declare. * function.c (assign_temp): Use it. * gimplify.c (create_tmp_var): Relax the assertions on the type properties, not mandating constant size any more. (force_constant_size): New static function. (gimple_add_tmp_var): Use it, forcing variable size to a constant upper bound if it is not constant on entry. * ada/misc.c (gnat_type_max_size): Look at TYPE_ADA_SIZE if we have not been able to get a constant upper bound from TYPE_SIZE_UNIT. * gnat.dg/varsize_temp.adb: New test. From-SVN: r114938
Diffstat (limited to 'gcc/ada/misc.c')
-rw-r--r--gcc/ada/misc.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/gcc/ada/misc.c b/gcc/ada/misc.c
index 2f68e42..47206da 100644
--- a/gcc/ada/misc.c
+++ b/gcc/ada/misc.c
@@ -745,13 +745,40 @@ gnat_get_alias_set (tree type)
return -1;
}
-/* GNU_TYPE is a type. Return its maxium size in bytes, if known. */
+/* GNU_TYPE is a type. Return its maxium size in bytes, if known,
+ as a constant when possible. */
static tree
-gnat_type_max_size (gnu_type)
- tree gnu_type;
+gnat_type_max_size (tree gnu_type)
{
- return max_size (TYPE_SIZE_UNIT (gnu_type), true);
+ /* First see what we can get from TYPE_SIZE_UNIT, which might not be
+ constant even for simple expressions if it has already been gimplified
+ and 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,
+ typically not gimplified. */
+
+ if (!host_integerp (max_unitsize, 1)
+ && (TREE_CODE (gnu_type) == RECORD_TYPE
+ || TREE_CODE (gnu_type) == UNION_TYPE
+ || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ && TYPE_ADA_SIZE (gnu_type))
+ {
+ tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
+
+ /* If we have succeded in finding a constant, round it up to the
+ type's alignment and return the result in byte units. */
+
+ if (host_integerp (max_adasize, 1))
+ max_unitsize
+ = size_binop (CEIL_DIV_EXPR,
+ round_up (max_adasize, TYPE_ALIGN (gnu_type)),
+ bitsize_unit_node);
+ }
+
+ return max_unitsize;
}
/* GNU_TYPE is a type. Determine if it should be passed by reference by