更改 gcc/g++ abi 中的调用约定

Changing calling convention in gcc/g++ abi

我如何强制 gcc/g++ 不使用寄存器而只在 x86_64 中堆栈 将参数传递给函数, 就像它是 32 位版本 (并可能以这种方式获取函数结果)。 我知道它破坏了官方 ABI 以及调用方和被调用方 必须以这种方式编译才能正常工作。我不在乎 push/pop 或 mov/sub 方式 用来。我希望编译器应该有一个可以强制执行它的标志 但是我没找到。

看来你不能不破解 GCC 的源代码。

没有使用低效堆栈参数的标准 x86-64 调用约定。

GCC 只知道如何使用标准调用约定,在本例中为 x86-64 SysV 和 MS Windows fastcall 和 vectorcall。 (例如 __attribute__((ms_abi))vectorcall)。通常没有人想要这个; MS 的调用约定对于包装器或可变函数已经足够友好了。即使在为 Linux、MacOS、*BSD 等编译时,您也可以将其用于某些功能(由 __attribute__ 控制),如果有帮助的话。很难想象纯堆栈参数的用例。


GCC 允许您将寄存器指定为固定(GCC 从未触及,如 -ffixed-rdi)、调用破坏或调用保留。 但是使用带有参数传递寄存器的那些只会产生错误的代码,而不是你想要的。

例如

int foo(int a, int b, int c);

void caller(int x) {
    foo(1,2,3);
    //foo(4,x,6);
}

compiled by gcc9.2 -O3 -fcall-saved-rdi

caller:
        push    rdi
        mov     edx, 3
        mov     esi, 2
        pop     rdi
        jmp     foo

它 saves/restores RDI 但在调用 foo.

之前没有在其中放入 1

并且它不会将 RDI 排除在 arg 传递序列之外并在以后碰撞其他 args。 (我在想你可以发明一个调用约定,其中所有的 arg 传递寄存器都是 fixedcall-saved,也许让 GCC 回退到堆栈 args。但是不行。)