------- Comment #8 from matz at gcc dot gnu dot org 2008-02-22 23:40 ------- I can confirm this, the code in foo is definitely wrong. When I compile the (standard compliant, unlike the example from comment #4) with 4.2 or 4.3 on x86-64, with -O or -O2 it breaks:
% cat foo.c long align; int foo (int flag) { int variable; if (flag == 0) return 42; align = (long)&variable; return foo (flag - 1); } The asm code for foo(): foo: subq $16, %rsp testl %edi, %edi movl $42, %eax je .L4 leaq 12(%rsp), %rax subl $1, %edi movq %rax, align(%rip) call foo .L4: addq $16, %rsp ret It's clear that this misaligns the stack for the next calls. On entry it's 8 mod 16, after the rsp adjustment it's still 8 mod 16, so in front of the call it's also 8 mod 16, and boom. Just before calls %rsp needs to be 0 mod 16. It seems to be important that this is a recursive call. This body does a 'sub $24', i.e. is correct: int bar(int); int foo (int flag) { int variable; if (flag == 0) return 42; align = (long)&variable; return bar (flag - 1); } The same is true, when I instead add a second call in the body (to bar()), then the incoming argument is stored in %rbx, which needs saving, so there's a push, and still a 'sub $16', i.e. again adjusting correctly. -- matz at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jh at suse dot cz, matz at | |gcc dot gnu dot org GCC target triplet|i386-apple-darwin8.11.1 |x86_64 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35271