From b2c3bcf47b9131455a7fccfaa699269ae108d76b Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 16 Nov 2007 08:52:51 +0000 Subject: [PATCH] utils2.c (build_call_alloc_dealloc): Move the code retrieving an allocator return value from a super-aligned address... 2007-11-16 Olivier Hainque ada/ * utils2.c (build_call_alloc_dealloc) : Move the code retrieving an allocator return value from a super-aligned address from here to ... * trans.c (gnat_to_gnu) : ... 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 --- gcc/ada/ChangeLog | 8 +++++ gcc/ada/trans.c | 33 +++++++++++++++++- gcc/ada/utils2.c | 34 +------------------ gcc/testsuite/ChangeLog | 4 +++ .../gnat.dg/release_unc_maxalign.adb | 19 +++++++++++ 5 files changed, 64 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/release_unc_maxalign.adb diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c90fe05c504..0faaf574946 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2007-11-16 Olivier Hainque + + * utils2.c (build_call_alloc_dealloc) : Move the code + retrieving an allocator return value from a super-aligned address from + here to ... + * trans.c (gnat_to_gnu) : ... here, and don't + expect a super-aligned address for a fat or thin pointer. + 2007-11-14 Eric Botcazou * trans.c (call_to_gnu): Always set the source location on the call diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index cd3c6a6be0f..449f0f7fc3a 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), diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c index 350358f719b..b8f59477af5 100644 --- a/gcc/ada/utils2.c +++ b/gcc/ada/utils2.c @@ -1873,39 +1873,7 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, unsigned align, } else if (gnu_obj) - { - /* If the required alignement was greater than what the default - allocator guarantees, what we have in gnu_obj here is an address - dynamically adjusted to match the requirement (see build_allocator). - What we need to pass to free is the initial underlying allocator's - return value, which has been stored just in front of the block we - have. */ - - unsigned int default_allocator_alignment - = get_target_default_allocator_alignment () * BITS_PER_UNIT; - - if (align > default_allocator_alignment) - { - /* We set GNU_OBJ - as * (void **)((void *)GNU_OBJ - (void *)sizeof(void *)) - in two steps: */ - - /* GNU_OBJ (void *) = (void *)GNU_OBJ - (void *)sizeof (void *)) */ - gnu_obj - = build_binary_op (MINUS_EXPR, ptr_void_type_node, - convert (ptr_void_type_node, gnu_obj), - convert (ptr_void_type_node, - TYPE_SIZE_UNIT (ptr_void_type_node))); - - /* GNU_OBJ (void *) = *(void **)GNU_OBJ */ - gnu_obj - = build_unary_op (INDIRECT_REF, NULL_TREE, - convert (build_pointer_type (ptr_void_type_node), - gnu_obj)); - } - - return build_call_1_expr (free_decl, gnu_obj); - } + return build_call_1_expr (free_decl, gnu_obj); /* ??? For now, disable variable-sized allocators in the stack since we can't yet gimplify an ALLOCATE_EXPR. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ec46967d4c8..0ef30d2a02e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-11-16 Olivier Hainque + + * gnat.dg/release_unc_maxalign.adb: New test. + 2007-11-16 Jakub Jelinek PR c++/34100 diff --git a/gcc/testsuite/gnat.dg/release_unc_maxalign.adb b/gcc/testsuite/gnat.dg/release_unc_maxalign.adb new file mode 100644 index 00000000000..245ce2190fe --- /dev/null +++ b/gcc/testsuite/gnat.dg/release_unc_maxalign.adb @@ -0,0 +1,19 @@ +-- { dg-do run } + +with Ada.Unchecked_Deallocation; + +procedure Release_UNC_Maxalign is + + type List is array (Natural range <>) of Integer; + for List'Alignment use Standard'Maximum_Alignment; + + type List_Access is access all List; + + procedure Release is new Ada.Unchecked_Deallocation + (Object => List, Name => List_Access); + + My_List : List_Access; +begin + My_List := new List (1 .. 3); + Release (My_List); +end; -- 2.30.2