aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJosh Conner <jconner@apple.com>2007-01-04 01:37:15 +0000
committerJosh Conner <jconner@gcc.gnu.org>2007-01-04 01:37:15 +0000
commit7816b87eb16eea7819a8b232f69fa1b9a7418bf7 (patch)
tree186a95381a2932a55c3a3134f0868b1aef0b3390 /gcc
parent4e8b35902bb2e407608a2425a7a211be4ccfacc5 (diff)
downloadgcc-7816b87eb16eea7819a8b232f69fa1b9a7418bf7.zip
gcc-7816b87eb16eea7819a8b232f69fa1b9a7418bf7.tar.gz
gcc-7816b87eb16eea7819a8b232f69fa1b9a7418bf7.tar.bz2
re PR middle-end/29683 (Arg split between stack/regs can cause stack corruption)
2007-03-01 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-03-01 Josh Conner <jconner@apple.com> PR middle-end/29683 * gcc.dg/pr29683.c: New. From-SVN: r120425
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/calls.c46
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr29683.c43
4 files changed, 94 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b59cc9a..be703c7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2007-01-03 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-03 Robert Kennedy <jimbob@google.com>
* tree-cfg.c (tree_merge_blocks): Release SSA_NAME phi results
diff --git a/gcc/calls.c b/gcc/calls.c
index bdb8167..c0d1f8c 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1355,9 +1355,13 @@ compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals
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)
@@ -1366,9 +1370,23 @@ compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals
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)
@@ -1386,9 +1404,21 @@ compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals
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
@@ -4056,7 +4086,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index daab71d..2406668 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-01-03 Josh Conner <jconner@apple.com>
+
+ PR middle-end/29683
+ * gcc.dg/pr29683.c: New.
+
2007-01-03 Jakub Jelinek <jakub@redhat.com>
PR c++/28217
diff --git a/gcc/testsuite/gcc.dg/pr29683.c b/gcc/testsuite/gcc.dg/pr29683.c
new file mode 100644
index 0000000..4bed679
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr29683.c
@@ -0,0 +1,43 @@
+/* { 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;
+}
+