authorgravatar for motiejus@jakstys.ltMotiejus Jakštys <motiejus@jakstys.lt> 2026-02-15 20:41:19+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-25 20:34:08+01:00
log56253d9e31c0576f024d95929a8fe26428b35176
tree33d1bdaa7cf02b1cf171d37a263a7ac24ee62eaa
parente0173c2ce01890ea71ab7660f2ecdeda29956f77

x86_64 codegen: fix RoundMode vroundss immediate value

Quoting Vol. 2B 4-590 of [Intel SSA manual][1]: > Bit 3 of the immediate byte controls processor behavior for a precision exception <...> The Direction struct is incorrectly sized to 4 bits, which pushes the precision exception bit to the reserved bits, which helpfully crashes under valgrind (but works on real hardware, since CPU ignores it): `` const std = @import("std"); noinline fn ceil(x: f32) f32 { return @ceil(x); } test "ceil" { try std.testing.expectEqual(@as(f32, 2.0), ceil(1.5)); } ``` With Zig 0.15.1: ``` $ zig test -fno-llvm -mcpu x86_64_v3 -fvalgrind ceil_test.zig --test-cmd valgrind --test-cmd --quiet --test-cmd-bin Illegal instruction at address 0x102d14d /home/motiejus/code/ceil_test.zig:4:5: 0x102d14d in ceil (ceil_test.zig) return @ceil(x); ^ /home/motiejus/code/ceil_test.zig:8:52: 0x102d097 in test.ceil (ceil_test.zig) try std.testing.expectEqual(@as(f32, 2.0), ceil(1.5)); ^ /nix/store/n81qdpd96d86ngfv5bqymy26b8kqm654-zig-0.15.1/lib/compiler/test_runner.zig:218:25: 0x1167e80 in mainTerminal (test_runner.zig) if (test_fn.func()) |_| { ^ /nix/store/n81qdpd96d86ngfv5bqymy26b8kqm654-zig-0.15.1/lib/compiler/test_runner.zig:66:28: 0x11610a1 in main (test_runner.zig) return mainTerminal(); ^ /nix/store/n81qdpd96d86ngfv5bqymy26b8kqm654-zig-0.15.1/lib/std/start.zig:618:22: 0x115ae3d in posixCallMainAndExit (std.zig) root.main(); ^ /nix/store/n81qdpd96d86ngfv5bqymy26b8kqm654-zig-0.15.1/lib/std/start.zig:232:5: 0x115a6d1 in _start (std.zig) asm volatile (switch (native_arch) { ^ ???:?:?: 0x0 in ??? (???) error: the following test command crashed: valgrind --quiet /home/motiejus/.cache/zig/o/7cc564b5410fc3facdb6e8768643074e/test ``` Zig 0.15.1 with this patch: ``` zig/zig3 test -fno-llvm -mcpu x86_64_v3 -fvalgrind ceil_test.zig --test-cmd valgrind --test-cmd --quiet --test-cmd-bin All 1 tests passed. ``` Looking through `CodeGen.zig` it _seems_ like the same RoundMode struct is used for vroundss/vroundps/vcvtps2ph, so update the comment while we're at it. But I am only 90% sure it's true. [1]: https://cdrdv2.intel.com/v1/dl/getContent/671200

1 files changed, 3 insertions(+), 3 deletions(-)

src/codegen/x86_64/bits.zig+3-3
......@@ -178,15 +178,15 @@ pub const Condition = enum(u5) {
178178 }
179179};
180180
181/// The immediate operand of vcvtps2ph.
182pub const RoundMode = packed struct(u5) {
181/// The immediate operand of vroundss/vroundps/vcvtps2ph/round??.
182pub const RoundMode = packed struct(u4) {
183183 direction: Direction = .mxcsr,
184184 precision: enum(u1) {
185185 normal = 0b0,
186186 inexact = 0b1,
187187 } = .normal,
188188
189 pub const Direction = enum(u4) {
189 pub const Direction = enum(u3) {
190190 /// Round to nearest (even)
191191 nearest = 0b0_00,
192192 /// Round down (toward -∞)