aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2003-09-14 10:07:51 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2003-09-14 10:07:51 +0000
commit975f381876699c55c3802e2d102eb0d9e1dcd6b3 (patch)
tree8d4bc0c5b6278c4ecbb34d3389d0f7d3a7bc36f4 /gcc
parent011d50d946a1c854e19d0be0aff69de6f97f6eaf (diff)
downloadgcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.zip
gcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.tar.gz
gcc-975f381876699c55c3802e2d102eb0d9e1dcd6b3.tar.bz2
function.c (STACK_BYTES): Move definition to head of file.
* function.c (STACK_BYTES): Move definition to head of file. (assign_parms): Don't pass current_function_pretend_args_size directly to SETUP_INCOMING_VARARGS. For partial register arguments, round current_function_pretend_args_size up to STACK_BYTES. Skip any excess before laying out the argument. From-SVN: r71372
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/function.c71
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030914-1.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030914-2.c21
5 files changed, 109 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 92fc97d..9c4ae39 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-09-14 Richard Sandiford <rsandifo@redhat.com>
+
+ * function.c (STACK_BYTES): Move definition to head of file.
+ (assign_parms): Don't pass current_function_pretend_args_size
+ directly to SETUP_INCOMING_VARARGS. For partial register arguments,
+ round current_function_pretend_args_size up to STACK_BYTES. Skip any
+ excess before laying out the argument.
+
2003-09-14 Andreas Jaeger <aj@suse.de>
* objc/objc-act.c: Convert to ISO C90 prototypes.
diff --git a/gcc/function.c b/gcc/function.c
index 8227139..29c8422 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -76,6 +76,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define STACK_ALIGNMENT_NEEDED 1
#endif
+#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
+
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@@ -4339,6 +4341,7 @@ assign_parms (tree fndecl)
int last_named = 0, named_arg;
int in_regs;
int partial = 0;
+ int pretend_bytes = 0;
/* Set LAST_NAMED if this is last named arg before last
anonymous args. */
@@ -4453,10 +4456,17 @@ assign_parms (tree fndecl)
Also, indicate when RTL generation is to be suppressed. */
if (last_named && !varargs_setup)
{
+ int varargs_pretend_bytes = 0;
targetm.calls.setup_incoming_varargs (&args_so_far, promoted_mode,
- passed_type,
- &current_function_pretend_args_size, 0);
+ passed_type,
+ &varargs_pretend_bytes, 0);
varargs_setup = 1;
+
+ /* If the back-end has requested extra stack space, record how
+ much is needed. Do not change pretend_args_size otherwise
+ since it may be nonzero from an earlier partial argument. */
+ if (varargs_pretend_bytes > 0)
+ current_function_pretend_args_size = varargs_pretend_bytes;
}
/* Determine parm's home in the stack,
@@ -4500,8 +4510,43 @@ assign_parms (tree fndecl)
#ifdef FUNCTION_ARG_PARTIAL_NREGS
if (entry_parm)
- partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
- passed_type, named_arg);
+ {
+ partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
+ passed_type, named_arg);
+ if (partial
+#ifndef MAYBE_REG_PARM_STACK_SPACE
+ /* The caller might already have allocated stack space
+ for the register parameters. */
+ && reg_parm_stack_space == 0
+#endif
+ )
+ {
+ /* Part of this argument is passed in registers and part
+ is passed on the stack. Ask the prologue code to extend
+ the stack part so that we can recreate the full value.
+
+ PRETEND_BYTES is the size of the registers we need to store.
+ CURRENT_FUNCTION_PRETEND_ARGS_SIZE is the amount of extra
+ stack space that the prologue should allocate.
+
+ Internally, gcc assumes that the argument pointer is
+ aligned to STACK_BOUNDARY bits. This is used both for
+ alignment optimisations (see init_emit) and to locate
+ arguments that are aligned to more than PARM_BOUNDARY
+ bits. We must preserve this invariant by rounding
+ CURRENT_FUNCTION_PRETEND_ARGS_SIZE up to a stack
+ boundary. */
+ pretend_bytes = partial * UNITS_PER_WORD;
+ current_function_pretend_args_size
+ = CEIL_ROUND (pretend_bytes, STACK_BYTES);
+
+ /* If PRETEND_BYTES != CURRENT_FUNCTION_PRETEND_ARGS_SIZE,
+ insert the padding before the start of the first pretend
+ argument. */
+ stack_args_size.constant
+ = (current_function_pretend_args_size - pretend_bytes);
+ }
+ }
#endif
memset (&locate, 0, sizeof (locate));
@@ -4546,17 +4591,6 @@ assign_parms (tree fndecl)
if (partial)
{
-#ifndef MAYBE_REG_PARM_STACK_SPACE
- /* When REG_PARM_STACK_SPACE is nonzero, stack space for
- split parameters was allocated by our caller, so we
- won't be pushing it in the prolog. */
- if (reg_parm_stack_space == 0)
-#endif
- current_function_pretend_args_size
- = (((partial * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
- / (PARM_BOUNDARY / BITS_PER_UNIT)
- * (PARM_BOUNDARY / BITS_PER_UNIT));
-
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (GET_CODE (entry_parm) == PARALLEL)
@@ -4600,10 +4634,7 @@ assign_parms (tree fndecl)
#endif
)
{
- stack_args_size.constant += locate.size.constant;
- /* locate.size doesn't include the part in regs. */
- if (partial)
- stack_args_size.constant += current_function_pretend_args_size;
+ stack_args_size.constant += pretend_bytes + locate.size.constant;
if (locate.size.var)
ADD_PARM_SIZE (stack_args_size, locate.size.var);
}
@@ -5175,8 +5206,6 @@ assign_parms (tree fndecl)
#endif
#endif
-#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
-
current_function_args_size
= ((current_function_args_size + STACK_BYTES - 1)
/ STACK_BYTES) * STACK_BYTES;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4d0d6fe..b2f7a2f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-09-14 Richard Sandiford <rsandifo@redhat.com>
+
+ * gcc.c-torture/execute/20030914-[12].c: New tests.
+
2003-09-11 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11788
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030914-1.c b/gcc/testsuite/gcc.c-torture/execute/20030914-1.c
new file mode 100644
index 0000000..ab1c154
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030914-1.c
@@ -0,0 +1,26 @@
+/* On IRIX 6, PB is passed partially in registers and partially on the
+ stack, with an odd number of words in the register part. Check that
+ the long double stack argument (PC) is still accessed properly. */
+
+struct s { int val[16]; };
+
+long double f (int pa, struct s pb, long double pc)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ pc += pb.val[i];
+ return pc;
+}
+
+int main ()
+{
+ struct s x;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ x.val[i] = i + 1;
+ if (f (1, x, 10000.0L) != 10136.0L)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030914-2.c b/gcc/testsuite/gcc.c-torture/execute/20030914-2.c
new file mode 100644
index 0000000..38a8198
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030914-2.c
@@ -0,0 +1,21 @@
+/* On IRIX 6, PA is passed partially in registers and partially on the
+ stack. We therefore have two potential uses of pretend_args_size:
+ one for the partial argument and one for the varargs save area.
+ Make sure that these uses don't conflict. */
+
+struct s { int i[18]; };
+
+int f (struct s pa, int pb, ...)
+{
+ return pb;
+}
+
+struct s gs;
+
+int main ()
+{
+ if (f (gs, 0x1234) != 0x1234)
+ abort ();
+
+ exit (0);
+}