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