My C code snippet takes the address of an argument and stores it in a volatile memory location (preprocessed code):
void foo(unsigned int x) {
*(volatile unsigned int*)(0x4000000 + 0xd4) = (unsigned int)(&x);
}
int main() {
foo(1);
while(1);
}
I used an SVN version of GCC for compiling this code. At the end of function foo
I would expect to have the value 1
stored in the stack and, at 0x40000d4
, an address pointing to that value. When I compile without optimizations using the flag -O0
, I get the expected ARM7TMDI assembly output (commented for your convenience):
.align 2
.global foo
.type foo, %function
foo:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sub sp, sp, #8
str r0, [sp, #4] @ 3. Store the argument on the stack
mov r3, #67108864
add r3, r3, #212
add r2, sp, #4 @ 4. Address of the stack variable
str r2, [r3, #0] @ 5. Store the address at 0x40000d4
add sp, sp, #8
bx lr
.size foo, .-foo
.align 2
.global main
.type main, %function
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
stmfd sp!, {r4, lr}
mov r0, #1 @ 1. Pass the argument in register 0
bl foo @ 2. Call function foo
.L4:
b .L4
.size main, .-main
.ident "GCC: (GNU) 4.4.0 20080820 (experimental)"
It clearly stores the argument first on the stack and from there stores it at 0x40000d4
. When I compile with optimizations using -O1
, I get something unexpected:
.align 2
.global foo
.type foo, %function
foo:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sub sp, sp, #8
mov r2, #67108864
add r3, sp, #4 @ 3. Address of *something* on the stack
str r3, [r2, #212] @ 4. Store the address at 0x40000d4
add sp, sp, #8
bx lr
.size foo, .-foo
.align 2
.global main
.type main, %function
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
stmfd sp!, {r4, lr}
mov r0, #1 @ 1. Pass the argument in register 0
bl foo @ 2. Call function foo
.L4:
b .L4
.size main, .-main
.ident "GCC: (GNU) 4.4.0 20080820 (experimental)"
This time the argument is never stored on the stack even though something from the stack is still stored at 0x40000d4
.
Is this just expected/undefined behaviour? Have I done something wrong or have I in fact found a Compiler Bug™?