You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since structure has 16 bytes, s1 should be passed via 2 separate 64 bit registers. However the zig compiler seems to be passing s1 via the stack instead. In practice, that causes the s1 fields in the C function to receive the values passed as p2 and p3 .
If I add an additional field to the structure, forcing it to be bigger than 16 bytes, then the SystemV amd64 ABI expects that argument to be passed via the stack and the program works fine.
You can find more information about aggregate types in the SystemV amd64 ABI in the following article:
Same as in OP, you can see in the assembly that Zig passes S on the stack while gcc and clang pass it in registers.
If you reduce the number of floating-point arguments from 5 to 4, Zig behaves correctly. Perhaps the presence of 5 floating-point arguments passed in registers makes Zig think it has no registers left for passing arguments, even though it actually does still have integer registers that it should be using.
Interestingly, when I run your example with the native x86_64 backend (zig run ./main.zig ./a.c -lc -fno-llvm -fno-lld) it produces the expected output. Since Clang can compile an equivalent function call correctly, I would guess this is a bug in Zig's LLVM backend rather than a bug in LLVM itself.
@190n, I believe the problem is that the LLVM doesn't implement all the specific rules of the target ABI (as pointed in [1]) and it leaves for the frontends to deal with it. I'm not familiar with the zig compiler code, but there's a good chance the native zig backend is handling instead.
Zig Version
0.14.0-dev.2649+77273103a
Steps to Reproduce and Observed Behavior
The zig compiler is generating wrong C ABI calls for amd64 linux when invoking functions with struct arguments.
Given the following source files:
main.c
:a.h
:a.c
:The following commands produce:
However the expected output would be:
Since
structure
has 16 bytes,s1
should be passed via 2 separate 64 bit registers. However the zig compiler seems to be passings1
via the stack instead. In practice, that causes thes1
fields in the C function to receive the values passed asp2
andp3
.If I add an additional field to the structure, forcing it to be bigger than 16 bytes, then the SystemV amd64 ABI expects that argument to be passed via the stack and the program works fine.
You can find more information about aggregate types in the SystemV amd64 ABI in the following article:
https://yorickpeterse.com/articles/the-mess-that-is-handling-structure-arguments-and-returns-in-llvm/
Expected Behavior
Expected output:
The 3 fields from the structure should be passed to the C function via 2 separate 64 bit registers.
The text was updated successfully, but these errors were encountered: