authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-29 19:01:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-30 02:43:05-04:00
logc248af3bdcd17c334e742d53a7ac7bda2422a688
tree8d47cfaa0f653ef1b835c6e250178c763270000a
parent54454fd0102af8b25dbc85751d37fd265380d920

LLVM: fix lowering of untagged union types

The LLVM backend was calculating the amount of padding solely based on the payload size. However, in the case where there is no union tag, this fails to take into account alignment. Closes #11857

3 files changed, 24 insertions(+), 5 deletions(-)

lib/std/net/test.zig-3
......@@ -5,7 +5,6 @@ const mem = std.mem;
55const testing = std.testing;
66
77test "parse and render IPv6 addresses" {
8 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
98 if (builtin.os.tag == .wasi) return error.SkipZigTest;
109
1110 var buffer: [100]u8 = undefined;
......@@ -68,7 +67,6 @@ test "invalid but parseable IPv6 scope ids" {
6867}
6968
7069test "parse and render IPv4 addresses" {
71 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
7270 if (builtin.os.tag == .wasi) return error.SkipZigTest;
7371
7472 var buffer: [18]u8 = undefined;
......@@ -93,7 +91,6 @@ test "parse and render IPv4 addresses" {
9391}
9492
9593test "parse and render UNIX addresses" {
96 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
9794 if (builtin.os.tag == .wasi) return error.SkipZigTest;
9895 if (!net.has_unix_sockets) return error.SkipZigTest;
9996
src/codegen/llvm.zig+5-2
......@@ -2708,7 +2708,10 @@ pub const DeclGen = struct {
27082708 if (layout.most_aligned_field_size == layout.payload_size) {
27092709 break :t llvm_aligned_field_ty;
27102710 }
2711 const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
2711 const padding_len = if (layout.tag_size == 0)
2712 @intCast(c_uint, layout.abi_size - layout.most_aligned_field_size)
2713 else
2714 @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
27122715 const fields: [2]*const llvm.Type = .{
27132716 llvm_aligned_field_ty,
27142717 dg.context.intType(8).arrayType(padding_len),
......@@ -5756,7 +5759,7 @@ pub const FuncGen = struct {
57565759 // First set the non-null bit.
57575760 const indices: [2]*const llvm.Value = .{
57585761 index_type.constNull(), // dereference the pointer
5759 index_type.constInt(1, .False), // second field is the payload
5762 index_type.constInt(1, .False), // second field is the non-null bit
57605763 };
57615764 const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
57625765 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
test/behavior/union.zig+19
......@@ -1194,3 +1194,22 @@ test "union tag is set when initiated as a temporary value at runtime" {
11941194 var b: u32 = 1;
11951195 try (U{ .b = b }).doTheTest();
11961196}
1197
1198test "extern union most-aligned field is smaller" {
1199 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1200 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1203
1204 const U = extern union {
1205 in6: extern struct {
1206 family: u16,
1207 port: u16,
1208 flowinfo: u32,
1209 addr: [20]u8,
1210 },
1211 un: [110]u8,
1212 };
1213 var a: ?U = .{ .un = [_]u8{0} ** 110 };
1214 try expect(a != null);
1215}