aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/trans.c
diff options
context:
space:
mode:
authorOlivier Hainque <hainque@adacore.com>2007-11-16 08:52:51 +0000
committerOlivier Hainque <hainque@gcc.gnu.org>2007-11-16 08:52:51 +0000
commitb2c3bcf47b9131455a7fccfaa699269ae108d76b (patch)
tree40b460c86146bcdff53b9a8c9239404f72196fbe /gcc/ada/trans.c
parent823e5f7f9fb52d8e6a9bb2c97164cc593ae18e11 (diff)
downloadgcc-b2c3bcf47b9131455a7fccfaa699269ae108d76b.zip
gcc-b2c3bcf47b9131455a7fccfaa699269ae108d76b.tar.gz
gcc-b2c3bcf47b9131455a7fccfaa699269ae108d76b.tar.bz2
utils2.c (build_call_alloc_dealloc): Move the code retrieving an allocator return value from a super-aligned address...
2007-11-16 Olivier Hainque <hainque@adacore.com> ada/ * utils2.c (build_call_alloc_dealloc) <if gnu_obj>: Move the code retrieving an allocator return value from a super-aligned address from here to ... * trans.c (gnat_to_gnu) <case N_Free_Statement>: ... here, and don't expect a super-aligned address for a fat or thin pointer. testsuite/ * gnat.dg/release_unc_maxalign.adb: New test. From-SVN: r130221
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r--gcc/ada/trans.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index cd3c6a6..449f0f7 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -4565,7 +4565,9 @@ gnat_to_gnu (Node_Id gnat_node)
tree gnu_obj_type;
tree gnu_actual_obj_type = 0;
tree gnu_obj_size;
- int align;
+ unsigned int align;
+ unsigned int default_allocator_alignment
+ = get_target_default_allocator_alignment () * BITS_PER_UNIT;
/* If this is a thin pointer, we must dereference it to create
a fat pointer, then go back below to a thin pointer. The
@@ -4621,6 +4623,35 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_ptr, gnu_byte_offset);
}
+ /* If the object was allocated from the default storage pool, the
+ alignement was greater than what the allocator provides, and this
+ is not a fat or thin pointer, what we have in gnu_ptr here is an
+ address dynamically adjusted to match the alignment requirement
+ (see build_allocator). What we need to pass to free is the
+ initial allocator's return value, which has been stored just in
+ front of the block we have. */
+
+ if (No (Procedure_To_Call (gnat_node)) && align > default_allocator_alignment
+ && ! TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type))
+ {
+ /* We set GNU_PTR
+ as * (void **)((void *)GNU_PTR - (void *)sizeof(void *))
+ in two steps: */
+
+ /* GNU_PTR (void *) = (void *)GNU_PTR - (void *)sizeof (void *)) */
+ gnu_ptr
+ = build_binary_op (MINUS_EXPR, ptr_void_type_node,
+ convert (ptr_void_type_node, gnu_ptr),
+ convert (ptr_void_type_node,
+ TYPE_SIZE_UNIT (ptr_void_type_node)));
+
+ /* GNU_PTR (void *) = *(void **)GNU_PTR */
+ gnu_ptr
+ = build_unary_op (INDIRECT_REF, NULL_TREE,
+ convert (build_pointer_type (ptr_void_type_node),
+ gnu_ptr));
+ }
+
gnu_result = build_call_alloc_dealloc (gnu_ptr, gnu_obj_size, align,
Procedure_To_Call (gnat_node),
Storage_Pool (gnat_node),