zig
zig copied to clipboard
miscompilation possibly related to union layout
Zig Version
0.11.0-dev.3978+711b4e93e
Steps to Reproduce and Observed Behavior
const std = @import("std");
const Inner = union {
integer: u32,
string: [8]u8, // modifying the size of this field will change the behavior
// you could try out [4]u8 or [12]u8
};
const Outer = union {
unreachable_inner: Inner,
params: [16]u8,
};
pub fn foo(params: [16]u8) Outer {
var id: ?u32 = null;
std.mem.doNotOptimizeAway(&id);
if (id) |id_obj| {
return .{ .unreachable_inner = .{ .integer = id_obj } };
}
return .{ .params = params };
}
pub fn main() void {
var val1 = [16]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
std.debug.print("{any}\n", .{val1});
const val2 = foo(val1);
std.debug.print("{any}\n", .{val2.params});
}
running zig run file.zig -O ReleaseSafe will output:
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
{ 0, 1, 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, 13, 14, 15 }
There is a zero at index 8. This only happens in ReleaseSafe. I did not observe this behavior in 0.10.1.
https://godbolt.org/z/qc3MsW7d6
Expected Behavior
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
We output llvm for unions in the same way as clang does, as can be seen by the fact that this bug reproduces with clang.
Moving this to the 0.12.0 milestone since it's an issue to be solved in LLVM 17.
Not fixed by a63a1c5cb9fd31a57e8371e6cba5f316bd3f2a65 (LLVM 17).
This miscompilation frequently happens when parsing a JSON value with two or more nested objects, so maybe it makes sense to implement the workaround suggested in the LLVM issue.
Fixed by #17963.
Fixed by #17963.
That's a workaround, the issue stays open to track the upstream bug and a revert of the workaround.
@jacobly0, with LLVM 18 the workaround can probably now be reverted.