authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-06 07:27:55-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-06 14:11:31-05:00
log9ced27dace99da1f2bc704b4d5a7fabe9a62eca4
treeacaf279fce16c96e3efdd1fd2d648516264a9893
parent62e67a2b565e20f684319f5e59e1bddd79c988d3

x86_64: fix passing register-sized payload as non-reigster-sized union

Closes #17885

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

src/InternPool.zig+1-1
...@@ -1887,7 +1887,7 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {...@@ -1887,7 +1887,7 @@ pub fn loadUnionType(ip: *InternPool, key: Key.UnionType) UnionType {
1887 .namespace = type_union.data.namespace,1887 .namespace = type_union.data.namespace,
1888 .enum_tag_ty = enum_ty,1888 .enum_tag_ty = enum_ty,
1889 .int_tag_ty = enum_info.tag_ty,1889 .int_tag_ty = enum_info.tag_ty,
1890 .size = type_union.data.padding,1890 .size = type_union.data.size,
1891 .padding = type_union.data.padding,1891 .padding = type_union.data.padding,
1892 .field_names = enum_info.names,1892 .field_names = enum_info.names,
1893 .names_map = enum_info.names_map,1893 .names_map = enum_info.names_map,
src/arch/x86_64/CodeGen.zig+3-2
...@@ -15323,10 +15323,11 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15323,10 +15323,11 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
15323 const src_ty = self.typeOf(extra.init);15323 const src_ty = self.typeOf(extra.init);
15324 const src_mcv = try self.resolveInst(extra.init);15324 const src_mcv = try self.resolveInst(extra.init);
15325 if (layout.tag_size == 0) {15325 if (layout.tag_size == 0) {
15326 if (self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;15326 if (layout.abi_size <= src_ty.abiSize(mod) and
15327 self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;
1532715328
15328 const dst_mcv = try self.allocRegOrMem(inst, true);15329 const dst_mcv = try self.allocRegOrMem(inst, true);
15329 try self.genCopy(union_ty, dst_mcv, src_mcv);15330 try self.genCopy(src_ty, dst_mcv, src_mcv);
15330 break :result dst_mcv;15331 break :result dst_mcv;
15331 }15332 }
1533215333
test/behavior/union.zig+21
...@@ -1881,3 +1881,24 @@ test "union field is a pointer to an aligned version of itself" {...@@ -1881,3 +1881,24 @@ test "union field is a pointer to an aligned version of itself" {
18811881
1882 try expect(&e == e.next);1882 try expect(&e == e.next);
1883}1883}
1884
1885test "pass register-sized field as non-register-sized union" {
1886 const S = struct {
1887 fn taggedUnion(u: union(enum) { x: usize, y: [2]usize }) !void {
1888 try expectEqual(@as(usize, 42), u.x);
1889 }
1890
1891 fn untaggedUnion(u: union { x: usize, y: [2]usize }) !void {
1892 try expectEqual(@as(usize, 42), u.x);
1893 }
1894
1895 fn externUnion(u: extern union { x: usize, y: [2]usize }) !void {
1896 try expectEqual(@as(usize, 42), u.x);
1897 }
1898 };
1899
1900 var x: usize = 42;
1901 try S.taggedUnion(.{ .x = x });
1902 try S.untaggedUnion(.{ .x = x });
1903 try S.externUnion(.{ .x = x });
1904}