diff options
author | Olivier Hainque <hainque@adacore.com> | 2007-11-16 08:52:51 +0000 |
---|---|---|
committer | Olivier Hainque <hainque@gcc.gnu.org> | 2007-11-16 08:52:51 +0000 |
commit | b2c3bcf47b9131455a7fccfaa699269ae108d76b (patch) | |
tree | 40b460c86146bcdff53b9a8c9239404f72196fbe /gcc/ada/trans.c | |
parent | 823e5f7f9fb52d8e6a9bb2c97164cc593ae18e11 (diff) | |
download | gcc-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.c | 33 |
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), |