TL;DR;我正在寻找一种标准方法来基本上告诉编译器将发生在给定寄存器中的任何内容传递给下一个函数。 p>
基本上我有一个函数int bar(int a, int b, int c)
。在某些情况下 c
未使用,我希望能够在 c
未使用的情况下调用 bar
而无需修改 rdx
以任何方式。
例如,如果我有
int foo(int a, int b) {
int no_init;
return bar(a, b, no_init);
}
我希望程序集只是:
尾声
jmp bar
或正常通话
call bar
注意:clang
通常会产生我正在寻找的东西。但我不确定在更复杂的功能中是否总是如此,我希望每次构建时都不必检查程序集。
GCC
产生:
尾声
xorl %edx, %edx
jmp bar
或正常通话
xorl %edx, %edx
call bar
我可以使用内联汇编获得我想要的结果,即将 foo
(用于尾调用)更改为
int foo(int a, int b) {
asm volatile("jmp bar" : : :);
__builtin_unreachable();
}
编译成只是
jmp bar
我了解 xorl %edx, %edx
的性能影响尽可能接近于 0,但是
我想知道是否有标准的方法来实现这一点。
也就是说,对于任何给定的情况,我都可以找到一个 hack。但这需要我每次都验证程序集。我正在寻找一种基本上可以告诉编译器“传递寄存器中发生的任何内容”的方法。
查看示例:https://godbolt.org/z/eh1vK8
编辑:设置 -O3
时会发生这种情况。
最佳答案
I am wondering if there is a standard way to achieve this.
I.e I can probably find a hack for it for any given case. But that will require me verifying the assembly each time. I am looking for a method that you can basically tell the compiler "pass whatever happened to be in register".
不,没有标准的方法可以在 C 或 C++ 中实现它。这两种语言都不涉及任何较低级别的函数调用语义,甚至不承认 CPU 寄存器的存在,* 并且这两种语言都要求每个函数调用都提供与所有非可选参数相对应的参数(只是 C 中的“所有声明的参数”)。
For example if I have
int foo(int a, int b) { int no_init; return bar(a, b, no_init); }
...然后,由于使用了不确定的 no_init
的值,您将获得 未定义的行为。无论任何特定的 C 或 C++ 实现完全接受它,它的定义都是非标准的。
如果你想调用bar()
,但你不关心作为第三个参数传递什么值,那为什么不直接选择一个方便的值来传递呢?零,例如:
return bar(a, b, 0);
*就任一种语言标准而言,即使是 register
关键字也不这样做。
关于c++ - 让编译器在调用函数之前忽略设置参数寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65646278/