This is the mail archive of the
mailing list for the GCC project.
Re: alloca attribute?
Perry Smith writes:
> On Nov 29, 2006, at 4:19 AM, Andrew Haley wrote:
> > Perry Smith writes:
> >> I wrote a class that switches the stack to a new area. This is for
> >> the power PC.
> >> In the text below, I'll use main, testit, and newStack. main is the
> >> main program, testit is a function that main calls, and newStack is
> >> the method that switches the stack to the new space. main calls
> >> testit which calls s.newStack. (s is an instance of the class that
> >> switches the stack).
> >> The purpose of separating main and testit is so I can verify that
> >> returning from testit works properly.
> >> newStack gets the current value of r1 (the stack pointer) and copies
> >> the last two stack frames (which would be the stack frame for testit
> >> and newStack) to the top of some allocated memory. It alters r1(0)
> >> (the previous stack value for newStack) in the new memory to point to
> >> the address of testit's new stack frame. It sets r1 up to the base
> >> of this new area and returns.
> > OK, before we go any further. Did you write and test DWARF unwinder
> > information for newStack?
> No, I did not. I thought it would be too big a task and I'm
> willing to put a try/catch after the stack has been changed so the
> unwind does not need to go through this. This may be naive. (See
> more below).
You'll need unwinder data, sooner or later. But let's leave it for
later, it's not strictly relevant to what you need now.
> >> With g++ and no optimization, this works. When newStack returns,
> >> it consumes its stack frame in the new memory leaving only testit's
> >> new stack frame and r1 pointing to the base of the new stack from
> >> for testit. When testit returns, it loads r1 with r1(0) and
> >> returns. This properly puts r1 back to main's stack frame.
> >> If I put -O3, then at the return of testit, instead of loading r1
> >> with r1(0), just adds in the size of the stack frame (and assumes
> >> that r1 has not been munged with). I presume this is faster. I
> >> know that xlc does the same thing. As a result, when we return
> >> back to main, the stack pointer is off in the weeds somewhere.
> > I get the feeling I'm not understanding something here. As long as
> > newStack is correct and handles all registers according to the ABI,
> > there shouldn't be any trouble.
> I'm sure you understand this better than I do. Can you point me to
> the info needed for the DWARF unwinder you mention above? That may
> educate me more.
> It still seems I am going to have problems so I will try and repeat
> the symptom:
> The code generated to return from a function can have two forms.
> Logically, it is a three step process. Pick up the return address
> which is located at r1(8) (assuming a 32 bit system) into a
> register (like r0), replace r1 with r1(0) which moves r1 to point
> to the previous stack frame, and then branch to what was at r1(8).
> But in optimized code, the compiler does not load r1 with r1(0).
> It assumes that r1 has not changed, and it knows the size of the
> stack frame, it just adds the size of the stack frame to r1. This
> will be the same address if r1 has not been changed.
> It seems like (but I may be wrong), even with the DWARF unwinder
> information, the compiler will still produce the code that adds the
> size of the stack from to r1 to get r1 to point to the previous
> stack frame instead of loading r1 with r1 (0).
Sure, but why would it matter? Your newStack routine should do
save caller registers somewhere
load new stack and frame pointer
call <foo> -- whatever it is you want to run on the new stack
restore caller registers, including stack and frame pointer
so it should not metter how the caller of newStack uses its stack
frame or what foo does. As long as you conform to the ABI you'll be