gpt4 book ai didi

c - 为什么 GCC 的 __attribute__((__ms_abi__)) 返回值与 MSVC 不同?

转载 作者:行者123 更新时间:2023-12-05 04:28:27 31 4
gpt4 key购买 nike

x86 Function Attributes在 GCC 文档中这样说:

On 32-bit and 64-bit x86 targets, you can use an ABI attribute to indicate which calling convention should be used for a function. The ms_abi attribute tells the compiler to use the Microsoft ABI, while the sysv_abi attribute tells the compiler to use the System V ELF ABI, which is used on GNU/Linux and other systems. The default is to use the Microsoft ABI when targeting Windows. On all other systems, the default is the System V ELF ABI.

但是考虑一下这个 C 代码:

#include <assert.h>

#ifdef _MSC_VER
#define MS_ABI
#else
#define MS_ABI __attribute__((__ms_abi__))
#endif

typedef struct {
void *x, *y;
} foo;

static_assert(sizeof(foo) == 8, "foo must be an 8-byte structure");

foo MS_ABI f(void *x, void *y) {
foo rv;
rv.x = x;
rv.y = y;
return rv;
}

gcc -O2 -m32 将其编译为:

f:
mov eax, DWORD PTR [esp+4]
mov edx, DWORD PTR [esp+8]
mov DWORD PTR [eax], edx
mov edx, DWORD PTR [esp+12]
mov DWORD PTR [eax+4], edx
ret

但是 cl/O2 将它编译成这样:

_x$ = 8                                       ; size = 4
_y$ = 12 ; size = 4
_f PROC ; COMDAT
mov eax, DWORD PTR _x$[esp-4]
mov edx, DWORD PTR _y$[esp-4]
ret 0
_f ENDP

Godbolt link

这些显然使用了不兼容的调用约定。 Argument Passing and Naming Conventions在 MSDN 上是这样说的:

Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures.

这意味着 MSVC 是正确的。那么为什么 GCC 使用指向隐藏返回结构的指针方法,即使返回值是一个 8 字节结构?这是 GCC 中的错误,还是我不允许像我想的那样使用 ms_abi

最佳答案

这对我来说似乎是错误的。 i386 SysV 仅返回寄存器中的 int64_t,而不是相同大小的结构,但也许 GCC 忘记将其考虑到 ms_abi。 gcc -mabi=ms ( docs ) 也有同样的问题。

即使是 -mabi=ms 通常也不会在不同的情况下更改结构布局,或者对于 x86-64 使 long 成为 32 位类型。但是您的结构在两个 ABI 中确实具有相同的布局,因此您希望它以 MSVC 调用者想要的方式返回。但这并没有发生。

这不是 IIRC 我第一次听说 __attribute__((ms_abi))-mabi=ms 中的错误。但是你正确地使用了它;在 64 位代码中,这会影响它查看的 arg 传递寄存器。

Clang 生成与 GCC 相同的 asm,但这并不重要,因为它警告说此目标不支持“ms_abi”调用约定。这是我们期望从 i386 SysV 获得的 asm。 (而且 Godbolt 没有 clang-cl。)


非常感谢您将其作为 bug #105932 报告给 GCC .

(有趣的是,当它选择使用 SSE 或 AVX 时,它会分别加载两个双字堆栈参数并将它们混合在一起,而不是 movq 加载。我想这可以避免可能的存储转发停顿,如果不过,调用者没有使用单个 64 位存储来编写参数。)

关于c - 为什么 GCC 的 __attribute__((__ms_abi__)) 返回值与 MSVC 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72588712/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com