Optimization 为什么GCC坚持非叶调用方将CBV结构复制到堆栈中?
考虑以下C99代码:Optimization 为什么GCC坚持非叶调用方将CBV结构复制到堆栈中?,optimization,gcc,call,cpu-registers,Optimization,Gcc,Call,Cpu Registers,考虑以下C99代码: #include <stdio.h> #include <stdint.h> struct baz { uint64_t x, y; }; uint64_t foo(uint64_t a, uint64_t b, struct baz c) { return a + b + c.x + c.y; } void bar(uint64_t a, uint64_t b, struct baz c) { printf("%lu\n",
#include <stdio.h>
#include <stdint.h>
struct baz { uint64_t x, y; };
uint64_t foo(uint64_t a, uint64_t b, struct baz c)
{
return a + b + c.x + c.y;
}
void bar(uint64_t a, uint64_t b, struct baz c)
{
printf("%lu\n", a);
}
(注意,a
和b
在%rsi
和%rdi
中传递,c
在%rcx
和%rdx
中传递)
我可以推测的唯一原因是某种ABI需求(例如,与longjmp的交互)。我找不到GCC的任何优化(-f
)选项,也找不到禁止此行为的GCC特定注释。用寄存器注释c
没有帮助
这种情况也会发生在不同的目标上。(值得注意的是,在TileGX上,foo
在堆栈上分配和释放了空间,但没有存储任何内容。)我已经测试了GCC 4.4.6和4.6.1
这是预期的行为还是GCC中的错误?不管是哪种方式,都有办法解决它(除了使用引用调用或确保bar
可以是一片叶子之外)?这个缺点与bug中提到的相同,最新版本的GCC(4.7.2)中提供了补丁
原因大致是对printf
(或任何函数)的调用被认为能够访问内存中的任何内容,包括基于堆栈的局部变量。该修补程序会导致被调用方认为无法访问基于堆栈的局部变量
.file "pbv.c"
.text
.p2align 4,,15
.globl foo
.type foo, @function
foo:
.LFB22:
.cfi_startproc
leaq (%rcx,%rdx), %rdx
leaq (%rdx,%rdi), %rdi
leaq (%rdi,%rsi), %rax
ret
.cfi_endproc
.LFE22:
.size foo, .-foo
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%lu\n"
.text
.p2align 4,,15
.globl bar
.type bar, @function
bar:
.LFB23:
.cfi_startproc
movq %rdx, -24(%rsp)
movl $.LC0, %esi
movq %rdi, %rdx
xorl %eax, %eax
movl $1, %edi
movq %rcx, -16(%rsp)
jmp __printf_chk
.cfi_endproc
.LFE23:
.size bar, .-bar
.ident "GCC: (Ubuntu/Linaro 4.4.6-11ubuntu2) 4.4.6"
.section .note.GNU-stack,"",@progbits