From 274949fdbb7a98d374d5e994110dbfd639c70acf Mon Sep 17 00:00:00 2001 From: Justus Klausecker Date: Mon, 29 Jun 2026 22:12:49 +0200 Subject: [PATCH] wasm: lower `packed union` backing integer type correctly `IntType.fromType` would previously set the signedness of any backing int of a `packed union` to `unsigned` unconditionally which caused comparisons of packed unions with large, signed backing integers to miscompile. Packed unions are now lowered correctly to their actual backing int type. --- src/codegen/wasm/CodeGen.zig | 16 ++++------------ test/behavior/packed-struct.zig | 13 +++++++++++++ test/behavior/packed-union.zig | 13 +++++++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 8d203139b8854c4913902087f033d26af520c60d..284bce953a0590c6c9a602db78714aa51ad349b4 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -2527,18 +2527,10 @@ const IntType = struct { .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable, }, - .struct_type => { - const loaded_struct = ip.loadStructType(ty_index); - switch (loaded_struct.layout) { - .auto, .@"extern" => unreachable, - .@"packed" => ty_index = loaded_struct.packed_backing_int_type, - } - }, - .union_type => return switch (ip.loadUnionType(ty_index).layout) { - .auto, .@"extern" => unreachable, - .@"packed" => .{ .is_signed = false, .bits = @intCast(ty.bitSize(zcu)) }, - }, - .enum_type => ty_index = ip.loadEnumType(ty_index).int_tag_type, + .enum_type, + .struct_type, + .union_type, + => ty_index = Type.fromInterned(ty_index).backingIntType(zcu).toIntern(), .error_set_type, .inferred_error_set_type => return .{ .is_signed = false, .bits = zcu.errorSetBits() }, else => unreachable, }; diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 986c15415486bf9c23b7b879a9d305e1a3cfaed1..96585d056cdf4c13b1aff3610ad08088fc0bf61c 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -1261,3 +1261,16 @@ test "convert from/to backing int" { try S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); try comptime S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); } + +test "equality with wide backing integer" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 + + const S = packed struct(i200) { + x: u200, + fn doTheTest(s: @This(), int: i200) !void { + try expect(s == @as(@This(), @bitCast(int))); + } + }; + try S.doTheTest(.{ .x = (1 << 200) - 1 }, -1); + try comptime S.doTheTest(.{ .x = (1 << 200) - 1 }, -1); +} diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index 44090943d487e3b52beae89a32baf5033d034a3d..4fd25526ce4a37deef7233b5b71120742604ce80 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -241,3 +241,16 @@ test "convert from/to backing int" { try U.doTheTest(.{ .a = 123 }); try comptime U.doTheTest(.{ .a = 123 }); } + +test "equality with wide backing integer" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 + + const U = packed union(i200) { + x: u200, + fn doTheTest(s: @This(), int: i200) !void { + try expect(s == @as(@This(), @bitCast(int))); + } + }; + try U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); + try comptime U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); +} -- 2.54.0