J'ai essayé avec GCC 4.7 et GCC 4.9, et je n'obtiens pas de pile exécutable dans ce cas là:
struct fib2_s {
int n;
int x;
};
void may_spawn(void (*)(void*), void*);
int fib(int n)
{
if (n < 2)
return n;
struct fib2_s f;
f.n = n - 2;
void subfunc_2 (void *data) {
struct fib2_s *f = data;
f->x = fib(f->n);
}
may_spawn (subfunc_2, &f);
int y = fib (n-1);
return f.x + y;
}
Code ASM généré:
.file "nested.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.text
.LHOTB0:
.p2align 4,,15
.globl fib
.type fib, @function
fib:
.LFB0:
.cfi_startproc
cmpl $1, %edi
jle .L2
jmp fib.part.0
.p2align 4,,10
.p2align 3
.L2:
movl %edi, %eax
ret
.cfi_endproc
.LFE0:
.size fib, .-fib
.section .text.unlikely
.LCOLDE0:
.text
.LHOTE0:
.section .text.unlikely
.LCOLDB1:
.text
.LHOTB1:
.p2align 4,,15
.type fib.part.0, @function
fib.part.0:
.LFB2:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
leal -2(%rdi), %eax
movl %edi, %ebx
movl $subfunc_2.1754, %edi
subq $16, %rsp
.cfi_def_cfa_offset 32
movq %rsp, %rsi
movl %eax, (%rsp)
call may_spawn
leal -1(%rbx), %edi
call fib
addl 4(%rsp), %eax
addq $16, %rsp
.cfi_def_cfa_offset 16
popq %rbx
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE2:
.size fib.part.0, .-fib.part.0
.section .text.unlikely
.LCOLDE1:
.text
.LHOTE1:
.section .text.unlikely
.LCOLDB2:
.text
.LHOTB2:
.p2align 4,,15
.type subfunc_2.1754, @function
subfunc_2.1754:
.LFB1:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
movl (%rdi), %eax
movq %rdi, %rbx
cmpl $1, %eax
jle .L7
movl %eax, %edi
call fib.part.0
.L7:
movl %eax, 4(%rbx)
popq %rbx
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1:
.size subfunc_2.1754, .-subfunc_2.1754
.section .text.unlikely
.LCOLDE2:
.text
.LHOTE2:
.ident "GCC: (GNU) 4.9.1"
.section .note.GNU-stack,"",@progbits
(Et GCC génère du code spécial pour ne pas créer de stack frame si on est dans le début de la fonction

)