push_rounding vs memcpy vs stack_pointer_delta

DJ Delorie dj@redhat.com
Fri Aug 29 04:27:00 GMT 2014


The m32c-elf with -mcpu=m32c has a word-aligned stack and uses pushes
for arguments (i.e. not accumulate_outgoing_args).  In this test case,
one of the arguments is memcpy'd into place, and an assert fails:

typedef struct {
  int a, b, c, d, e, f, g, h;
} foo;
int x;
void
dj (int a, int b, foo c)
{
  dj2 (x, a, b, c);
}

      if (pass == 0)
	{
	  . . .
	}
      else
	{
	  normal_call_insns = insns;

	  /* Verify that we've deallocated all the stack we used.  */
	  gcc_assert ((flags & ECF_NORETURN)
		      || (old_stack_allocated
			  == stack_pointer_delta - pending_stack_adjust));
	}

After much debugging, it turns out that the argument that's memcpy'd
to stack doesn't adjust stack_pointer_delta the same way that the
other arguments do (i.e. push_block and push_args don't adjust it
consistently, or something like that.)

I came up with this patch:

Index: expr.c
===================================================================
--- expr.c      (revision 214599)
+++ expr.c      (working copy)
@@ -4234,12 +4234,16 @@ emit_push_insn (rtx x, enum machine_mode
          /* Get the address of the stack space.
             In this case, we do not deal with EXTRA separately.
             A single stack adjust will do.  */
          if (! args_addr)
            {
              temp = push_block (size, extra, where_pad == downward);
+#ifdef PUSH_ROUNDING
+             if (CONST_INT_P (size))
+               stack_pointer_delta += INTVAL (size) + extra;
+#endif
              extra = 0;
            }
          else if (CONST_INT_P (args_so_far))
            temp = memory_address (BLKmode,
                                   plus_constant (Pmode, args_addr,
                                                  skip + INTVAL (args_so_far)));


But builds of libstdc++v3 demonstrate that sometimes
stack_pointer_delta *is* adjusted consistently, thus there must be
some more complex logic for determining when the extra adjustment
(i.e. my patch) should be made, or it's in the wrong place.

So... could someone more familiar with this code enlighten me on the
actual rules for what stack_pointer_delta means and when it gets
adjusted, and where (in theory) a memcpy'd argument on a push_args
target should update it (if at all)?

Thanks!
DJ



More information about the Gcc mailing list