Skip to content

Commit dce3b77

Browse files
committed
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
1 parent c69ff22 commit dce3b77

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

lib/std/net/test.zig

-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const mem = std.mem;
55
const testing = std.testing;
66

77
test "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

7069
test "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

9593
test "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
Original file line numberDiff line numberDiff line change
@@ -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
Original file line numberDiff line numberDiff line change
@@ -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+
1198+
test "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+
}

0 commit comments

Comments
 (0)