[arm-gnu] Re: Strange assembly generated in G++ ARM Thumb mode
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[arm-gnu] Re: Strange assembly generated in G++ ARM Thumb mode
- To: arm-gnu@xxxxxxxxxxxxxxxx
- Subject: [arm-gnu] Re: Strange assembly generated in G++ ARM Thumb mode
- From: Matt Fischer <mattfischer84@xxxxxxxxx>
- Date: Mon, 15 Aug 2011 15:34:43 -0500
Ping. Any takers on this? Or would it be better to ask the main GCC
list about it?
Thanks,
Matt
On Wed, Aug 10, 2011 at 12:32 PM, Matt Fischer <mattfischer84@xxxxxxxxx> wrote:
> I have a question about some assembly code that's being generated by
> G++. It looks wrong to me (and causes a crash when run), but I'm not
> yet entirely certain whether it's an error in the compiler or some
> kind of mistake in the code that it's compiling. I'd appreciate any
> insights.
>
> A test program that illustrates the problem is the following:
>
> -----------------------------------------------------------
>
> #include <boost/signal.hpp>
>
> bool func()
> {
> return false;
> }
>
> int main(int argc, char *argv[])
> {
> boost::signal<bool ()> sig;
> sig.connect(func);
> bool result = sig();
> }
>
> ------------------------------------------------------------
>
> When compiled with most combinations of ARM flags, this works just
> fine (this is G++ 4.5.2 on Windows, with Boost version 1.40).
> However, when I try to build this as -mthumb -Os, I get the following
> code sequence down inside some random Boost function:
>
> 00000000 <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<bool>::caller<boost::functi
> 0: b537 push {r0, r1, r2, r4, r5, lr}
> 2: 1c05 adds r5, r0, #0
> 4: ac01 add r4, sp, #4
> 6: 1c29 adds r1, r5, #0
> 8: 1c20 adds r0, r4, #0
> a: f7ff fffe bl 0
> <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<bo
> e: 1c28 adds r0, r5, #0
> 10: f7ff fffe bl 0
> <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<bo
> 14: 7820 ldrb r0, [r4, #0]
> 16: bc37 pop {r0, r1, r2, r4, r5}
> 18: bc02 pop {r1}
> 1a: 4708 bx r1
>
> I have no idea what this particular function does (it's Boost, so who
> really does), but stepping through this code in a debugger shows that
> its return value is getting corrupted. Examining the assembly reveals
> why. This function returns a bool, and you can see it loading up r0
> with the byte at [r4, #0] at the end of the function, in preparation
> for function return. However, immediately after that, we pop off
> stack contents into r0-r2, destroying this value, and causing the
> function to return garbage to its caller.
>
> If I change the type of the return from bool to int, the problem goes away:
>
> 00000000 <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<int>::caller<boost::functio
> 0: b513 push {r0, r1, r4, lr}
> 2: 1c04 adds r4, r0, #0
> 4: 1c21 adds r1, r4, #0
> 6: a801 add r0, sp, #4
> 8: f7ff fffe bl 0
> <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<in
> c: 1c20 adds r0, r4, #0
> e: f7ff fffe bl 0
> <boost::detail::postfix_increment_result<boost::signals::detail::slot_call_iterator<boost::signals::detail::call_bound0<in
> 12: 9801 ldr r0, [sp, #4]
> 14: bc16 pop {r1, r2, r4}
> 16: bc02 pop {r1}
> 18: 4708 bx r1
>
> This leads to a couple questions:
>
> 1) Why is GCC saving r0-r2 anyway? They're caller-saved, so it
> shouldn't have any problem overwriting them in the function.
> 2) Given that it is saving them, why is it restoring them at the
> expense of the function's return value?
> 3) Even in the second case, where the return value is being preserved
> properly, we're getting this return value from [sp, #4], which is the
> value that we're also going to then put into r2 during the final pop.
> Why are we saving registers to the stack and then turning around and
> using those locations as temp space?
>
> My best guess at this point is that we're pushing r0-r2 during the
> prologue as some poor man's way of creating temp space on the stack
> without needing a separate 'sub sp, #' instruction, but then we're
> forgetting about the fact that we're returning a value at the end of
> the function, so we accidentally pop over the top of r0 during the
> epilogue, or something like that.
>
> I always hate to be the idiot who cries "compiler bug" at the first
> sign of weirdness, only to eventually discover some more mundane
> solution, but this does seem pretty weird to me. Can anybody shed any
> light on what's going on here?
>
> Thanks,
> Matt
>