[Bug target/38952] [4.4 Regression] EH does not work.

dave dot korn dot cygwin at gmail dot com gcc-bugzilla@gcc.gnu.org
Sun Jan 25 06:05:00 GMT 2009



------- Comment #14 from dave dot korn dot cygwin at gmail dot com  2009-01-25 06:05 -------
Adding "-mpreferred-stack-boundary=2" to the command line generates correct
code.

Here are the diffs between code generated by that setting and the default
(-mpreferred-stack-boundary=4) for the start of the function:

--- eh-sb2.s    2009-01-25 05:24:46.718750000 +0000
+++ eh-sb4.s    2009-01-25 05:26:19.187500000 +0000
@@ -10,19 +10,20 @@
 _main:
        pushl   %ebp
        movl    %esp, %ebp
+       andl    $-16, %esp
        pushl   %edi
        pushl   %esi
        pushl   %ebx
-       subl    $68, %esp
-       movl    $___gxx_personality_sj0, -40(%ebp)
-       movl    $LLSDA0, -36(%ebp)
-       leal    -32(%ebp), %eax
-       leal    -12(%ebp), %edx
+       subl    $84, %esp
+       movl    $___gxx_personality_sj0, 52(%esp)
+       movl    $LLSDA0, 56(%esp)
+       leal    60(%esp), %eax
+       leal    80(%esp), %edx
        movl    %edx, (%eax)
        movl    $L5, %edx
        movl    %edx, 4(%eax)
        movl    %esp, 8(%eax)
-       leal    -64(%ebp), %eax
+       leal    28(%esp), %eax
        movl    %eax, (%esp)
        call    __Unwind_SjLj_Register


So.... I think I'm starting to grok what's happening here.  Because of the
larger stack alignment required, and because the incoming stack alignment is
only 8, not 16, we have to use an AND to mask and align the incoming esp.  Now
that means then that we have a hole of unknown size in our stack frame, just
below the frame pointer at the top end.  So because this gap is unkown, we
can't index down from the frame pointer %ebp to the rest of the stack frame any
more, which is why we have to turn the elimination basis upside down and
calculate all the eliminations upward from esp instead.

(The gap is in fact composed of two components.  The dynamic adjustment needed
to align the incoming stack, which cannot be known at compile time, and then
the extra space allocated to the stack frame to ensure its size is a multiple
of the alignment so that the lower end of the frame is also aligned.  Although
this second part is known at compile-time, as long as the first part is
unpredictable we have to do the eliminations from the stack base, not frame
pointer).

This is all fine for most stack frame contents, but it goes wrong in exactly
the same-but-opposite way if we're trying to access items of the stack frame
*above* the gap - and that's what's happening in my test case, because we're
trying to get the address of HARD_FRAME_POINTER, aka the value in $ebp, aka 4
or 8 bytes below the ARG_POINTER (compile-time known constant offset).

So the one or two items above the gap - the frame pointer and the return pc
value (Does this bug affect __builtin_return_address(0) as well, by any chance?
 I haven't checked) - would have to still be eliminated against
HARD_FRAME_POINTER and denied elimination against STACK_POINTER in the case
where there is going to be stack realignment in the prologue.  

And that is presumably the intention of this if clause in ix86_can_eliminate:

  if (stack_realign_fp)
    return ((from == ARG_POINTER_REGNUM
             && to == HARD_FRAME_POINTER_REGNUM)
            || (from == FRAME_POINTER_REGNUM
                && to == STACK_POINTER_REGNUM));
  else [ ... ]

I'll look at why it's not doing what it's supposed to.  One possibility is that
stack_realign_fp isn't becoming true until after the elimination has already
taken place.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38952



More information about the Gcc-bugs mailing list