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]

[PATCH] [4.1/4.2 regression - PR middle-end/29683


OK to apply the same fix to 4.1 and 4.2 branches for PR29683 (Arg split
between stack/regs can cause stack corruption) that I applied to
mainline?  Tested on arm-apple-darwin8 against 4.1 and 4.2 branches with
no regressions.

Mainline patch submitted here:

  http://gcc.gnu.org/ml/gcc-patches/2006-11/msg00046.html

Approved (with changes) here:

  http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01418.html

- Josh

:ADDPATCH middle-end:

2007-01-26  Josh Conner  <jconner@apple.com>

        PR middle-end/29683
        * calls.c (compute_argument_addresses): Set stack and stack_slot
        for partial args, too.
        (store_one_arg): Use locate.size.constant for the size when
        generating a save_area.


2007-01-26  Josh Conner  <jconner@apple.com>

	PR middle-end/29683
	* gcc.dg/pr29683.c: New.
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(revision 121180)
+++ gcc/calls.c	(working copy)
@@ -1356,9 +1356,13 @@ compute_argument_addresses (struct arg_d
 	  rtx slot_offset = ARGS_SIZE_RTX (args[i].locate.slot_offset);
 	  rtx addr;
 	  unsigned int align, boundary;
+	  unsigned int units_on_stack = 0;
+	  enum machine_mode partial_mode = VOIDmode;
 
 	  /* Skip this parm if it will not be passed on the stack.  */
-	  if (! args[i].pass_on_stack && args[i].reg != 0)
+	  if (! args[i].pass_on_stack
+	      && args[i].reg != 0
+	      && args[i].partial == 0)
 	    continue;
 
 	  if (GET_CODE (offset) == CONST_INT)
@@ -1367,9 +1371,23 @@ compute_argument_addresses (struct arg_d
 	    addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
 
 	  addr = plus_constant (addr, arg_offset);
-	  args[i].stack = gen_rtx_MEM (args[i].mode, addr);
-	  set_mem_attributes (args[i].stack,
-			      TREE_TYPE (args[i].tree_value), 1);
+
+	  if (args[i].partial != 0)
+	    {
+	      /* Only part of the parameter is being passed on the stack.
+		 Generate a simple memory reference of the correct size.  */
+	      units_on_stack = args[i].locate.size.constant;
+	      partial_mode = mode_for_size (units_on_stack * BITS_PER_UNIT,
+					    MODE_INT, 1);
+	      args[i].stack = gen_rtx_MEM (partial_mode, addr);
+	      set_mem_size (args[i].stack, GEN_INT (units_on_stack));
+	    }
+	  else
+	    {
+	      args[i].stack = gen_rtx_MEM (args[i].mode, addr);
+	      set_mem_attributes (args[i].stack,
+				  TREE_TYPE (args[i].tree_value), 1);
+	    }
 	  align = BITS_PER_UNIT;
 	  boundary = args[i].locate.boundary;
 	  if (args[i].locate.where_pad != downward)
@@ -1387,9 +1405,20 @@ compute_argument_addresses (struct arg_d
 	    addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
 
 	  addr = plus_constant (addr, arg_offset);
-	  args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
-	  set_mem_attributes (args[i].stack_slot,
-			      TREE_TYPE (args[i].tree_value), 1);
+
+	  if (args[i].partial != 0)
+	    {
+	      /* Only part of the parameter is being passed on the stack.
+		 Generate a simple memory reference of the correct size.  */
+	      args[i].stack_slot = gen_rtx_MEM (partial_mode, addr);
+	      set_mem_size (args[i].stack_slot, GEN_INT (units_on_stack));
+	    }
+	  else
+	    {
+	      args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
+	      set_mem_attributes (args[i].stack_slot,
+				  TREE_TYPE (args[i].tree_value), 1);
+	    }
 	  set_mem_align (args[i].stack_slot, args[i].locate.boundary);
 
 	  /* Function incoming arguments may overlap with sibling call
@@ -4059,7 +4088,7 @@ store_one_arg (struct arg_data *arg, rtx
 		  arg->save_area = assign_temp (nt, 0, 1, 1);
 		  preserve_temp_slots (arg->save_area);
 		  emit_block_move (validize_mem (arg->save_area), stack_area,
-				   expr_size (arg->tree_value),
+				   GEN_INT (arg->locate.size.constant),
 				   BLOCK_OP_CALL_PARM);
 		}
 	      else
/* { dg-do run } */
/* { dg-options "-Os -fno-inline-functions" } */

void abort (void);

typedef struct {
  int x[7];
} agg7;

typedef struct {
  int mbr1;
  int mbr2;
} agg2;

int expected = 31415;
agg7 filler;

int GetConst (agg7 filler, agg2 split)
{
  return expected;
}

void VerifyValues (agg7 filler, int last_reg, int first_stack, int second_stack)
{
  if (first_stack != 123 || second_stack != expected)
    abort ();
}

void RunTest (agg2 a)
{
  int result;
	
  result = GetConst (filler, a);
  VerifyValues (filler, 0, a.mbr1, result);
}

int main(void)
{
  agg2 result = {123, 456};
  RunTest (result);
  return 0;
}


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