diff options
author | Josh Conner <jconner@apple.com> | 2007-01-04 01:37:15 +0000 |
---|---|---|
committer | Josh Conner <jconner@gcc.gnu.org> | 2007-01-04 01:37:15 +0000 |
commit | 7816b87eb16eea7819a8b232f69fa1b9a7418bf7 (patch) | |
tree | 186a95381a2932a55c3a3134f0868b1aef0b3390 /gcc | |
parent | 4e8b35902bb2e407608a2425a7a211be4ccfacc5 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/calls.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr29683.c | 43 |
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; +} + |