This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA, PATCH, 4.4 regression] Fix PR middle-end/38028


Hello,

PR middle-end/38028 is a failure of SJLJ exception handling in some
(but not all) exception-related test cases on the SPU.

The problem turns out to be caused by a store to a reload save slot
clobbering the SJLJ context data structure that occupied an overlapping
area in the call stack.

This in turn was caused by that SJLJ context data not being properly
aligned to 16 bytes on the stack.  Because the SPU has no instruction
to store less that 16 bytes (one full register) at the same time, and
during reload it is not feasible to generate load-modify-write cycles
that are normally employed to implement smaller writes, all reload
slots -even those for smaller modes- must be 16 bytes wide.

To ensure this, the SPU back-end defines LOCAL_ALIGNMENT to force
*every* stack slot to be 16-byte aligned; and therefore the effective
size of every stack slot is 16 bytes as well.

However, this only works if *every* stack allocation respects the
alignment requirements implemented by LOCAL_ALIGNMENT (or rather
STACK_SLOT_ALIGNMENT these days).  Where assign_stack_local is left
to its own devices, it will always do so.  Most places that call
that routine overriding the default alignment choice will also
(directly or indirectly) take LOCAL_ALIGNMENT into account.

However, it turns out there are three places that do *not*, and
one of the happens to be sjlj_build_landing_pads, where the SJLJ
context is allocated.  All these places pass TYPE_ALIGN to the
assign_stack_local routine, presumably to account for the case
where a data type has a stricter alignment requirement than the
default stack alignment.  But this ignores the case where a type
has a *less* strict alignment requirement ...

The following patch changes those three locations to also call
STACK_SLOT_ALIGNMENT to give the back-end a chance to impose a
more strict requirement than what TYPE_ALIGN provides.

Note that the problem is already latent in 4.3, but it does not
show up as test case failures there, because in 4.3 reload slots
reside *above* stack slots for local variables.  Only after
http://gcc.gnu.org/ml/gcc-patches/2008-10/msg01012.html
changed the frame direction we now have the situation where reload
slots lie *below* local variables, which exposes the bug.

Tested on spu-elf with no regressions, fixes the following test cases:

FAIL: g++.dg/compat/eh/ctor1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/compat/eh/ctor2 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/compat/eh/new1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/compat/init/array5 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/eh/ctor1.C execution test
FAIL: g++.dg/eh/ctor2.C execution test
FAIL: g++.dg/eh/new1.C execution test
FAIL: g++.dg/init/array5.C execution test
FAIL: g++.dg/init/ctor1.C execution test
FAIL: g++.old-deja/g++.eh/fntry1.C execution test
FAIL: g++.old-deja/g++.eh/rethrow3.C execution test
FAIL: g++.old-deja/g++.eh/vbase1.C execution test
FAIL: g++.old-deja/g++.eh/vbase2.C execution test
FAIL: g++.old-deja/g++.mike/eh16.C execution test
FAIL: g++.old-deja/g++.mike/eh17.C execution test
FAIL: g++.old-deja/g++.mike/eh39.C execution test
FAIL: g++.old-deja/g++.mike/eh40.C execution test
FAIL: g++.old-deja/g++.mike/eh41.C execution test
FAIL: g++.old-deja/g++.other/vbase2.C execution test

OK for mainline?

Bye,
Ulrich


ChangeLog:

	PR middle-end/38028
	* function.c (assign_parm_setup_stack): Use STACK_SLOT_ALIGNMENT to
	determine alignment passed to assign_stack_local.
	(assign_parms_unsplit_complex): Likewise.
	* except.c (sjlj_build_landing_pads): Likewise.


Index: gcc/function.c
===================================================================
*** gcc/function.c	(revision 143924)
--- gcc/function.c	(working copy)
*************** assign_parm_setup_stack (struct assign_p
*** 2967,2976 ****
  
        if (data->stack_parm == 0)
  	{
  	  data->stack_parm
  	    = assign_stack_local (GET_MODE (data->entry_parm),
  				  GET_MODE_SIZE (GET_MODE (data->entry_parm)),
! 				  TYPE_ALIGN (data->passed_type));
  	  set_mem_attributes (data->stack_parm, parm, 1);
  	}
  
--- 2967,2979 ----
  
        if (data->stack_parm == 0)
  	{
+ 	  int align = STACK_SLOT_ALIGNMENT (data->passed_type,
+ 					    GET_MODE (data->entry_parm),
+ 					    TYPE_ALIGN (data->passed_type));
  	  data->stack_parm
  	    = assign_stack_local (GET_MODE (data->entry_parm),
  				  GET_MODE_SIZE (GET_MODE (data->entry_parm)),
! 				  align);
  	  set_mem_attributes (data->stack_parm, parm, 1);
  	}
  
*************** assign_parms_unsplit_complex (struct ass
*** 3032,3042 ****
  	    {
  	      rtx rmem, imem;
  	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (parm));
  
  	      /* split_complex_arg put the real and imag parts in
  		 pseudos.  Move them to memory.  */
! 	      tmp = assign_stack_local (DECL_MODE (parm), size,
! 					TYPE_ALIGN (TREE_TYPE (parm)));
  	      set_mem_attributes (tmp, parm, 1);
  	      rmem = adjust_address_nv (tmp, inner, 0);
  	      imem = adjust_address_nv (tmp, inner, GET_MODE_SIZE (inner));
--- 3035,3047 ----
  	    {
  	      rtx rmem, imem;
  	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (parm));
+ 	      int align = STACK_SLOT_ALIGNMENT (TREE_TYPE (parm),
+ 						DECL_MODE (parm),
+ 						TYPE_ALIGN (TREE_TYPE (parm)));
  
  	      /* split_complex_arg put the real and imag parts in
  		 pseudos.  Move them to memory.  */
! 	      tmp = assign_stack_local (DECL_MODE (parm), size, align);
  	      set_mem_attributes (tmp, parm, 1);
  	      rmem = adjust_address_nv (tmp, inner, 0);
  	      imem = adjust_address_nv (tmp, inner, GET_MODE_SIZE (inner));
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 143924)
--- gcc/except.c	(working copy)
*************** sjlj_build_landing_pads (void)
*** 2017,2027 ****
    if (sjlj_find_directly_reachable_regions (lp_info))
      {
        rtx dispatch_label = gen_label_rtx ();
! 
        crtl->eh.sjlj_fc
  	= assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
  			      int_size_in_bytes (sjlj_fc_type_node),
! 			      TYPE_ALIGN (sjlj_fc_type_node));
  
        sjlj_assign_call_site_values (dispatch_label, lp_info);
        sjlj_mark_call_sites (lp_info);
--- 2017,2029 ----
    if (sjlj_find_directly_reachable_regions (lp_info))
      {
        rtx dispatch_label = gen_label_rtx ();
!       int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
! 					TYPE_MODE (sjlj_fc_type_node),
! 					TYPE_ALIGN (sjlj_fc_type_node));
        crtl->eh.sjlj_fc
  	= assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
  			      int_size_in_bytes (sjlj_fc_type_node),
! 			      align);
  
        sjlj_assign_call_site_values (dispatch_label, lp_info);
        sjlj_mark_call_sites (lp_info);
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]