zig
zig copied to clipboard
Calling C function returning struct <16 bytes truncates result
Zig Version
0.11.0-dev.3395+1e7dcaa3a
Steps to Reproduce and Observed Behavior
A minimal example:
// vec.zig
const std = @import("std");
const vec = @cImport(@cInclude("./vec.c"));
pub fn main() void {
const v = vec.get_vec();
std.debug.print("{d} {d} {d}\n", .{v.x, v.y, v.z});
}
// vec.c
typedef struct { int x; int y; int z; } Vec;
Vec get_vec() {
Vec vec = { 1, 2, 3 };
return vec;
}
Running this with zig run -O ReleaseFast -I. vec.zig on x64 Linux outputs 1 2 0. ReleaseSafe gives identical results.
Expected Behavior
I would expect the program to output 1 2 3.
Debug mode does not have this problem. Moreover, adding a fourth component int w; to Vec fixes the problem.
It seems any similar struct smaller than 16 bytes gets truncated to 8 bytes when returned from a C function into a Zig function. I have tested this with a struct containing 12 uint8_ts, and one containing 4 structs each containing 3 uint8_t. My guess is that the C calling convention is not properly respected with optimizations enabled.
May be related to #14262.