authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-29 19:02:59+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-30 00:46:45+03:00
log2a4e89e0c9428b1ca59bc23c7c1d667c8ddb2304
tree69c4313e5f326b0b7964fd5b66d5d485e4003a45
parent312260124279027a248d669e6096c3ab603fa188

Type: correctly handle ABI align strat for optionals and error unions

Closes #12984

3 files changed, 41 insertions(+), 2 deletions(-)

src/type.zig+18-2
......@@ -3458,12 +3458,21 @@ pub const Type = extern union {
34583458 else => {},
34593459 }
34603460
3461 const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) {
3462 .scalar => |elem_size| elem_size,
3463 .val => switch (strat) {
3464 .sema_kit => unreachable,
3465 .eager => unreachable,
3466 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3467 },
3468 };
3469
34613470 // Optional types are represented as a struct with the child type as the first
34623471 // field and a boolean as the second. Since the child type's abi alignment is
34633472 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
34643473 // to the child type's ABI alignment.
34653474 return AbiSizeAdvanced{
3466 .scalar = child_type.abiAlignment(target) + child_type.abiSize(target),
3475 .scalar = child_type.abiAlignment(target) + payload_size,
34673476 };
34683477 },
34693478
......@@ -3478,7 +3487,14 @@ pub const Type = extern union {
34783487 }
34793488 const code_align = abiAlignment(Type.anyerror, target);
34803489 const payload_align = abiAlignment(data.payload, target);
3481 const payload_size = abiSize(data.payload, target);
3490 const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) {
3491 .scalar => |elem_size| elem_size,
3492 .val => switch (strat) {
3493 .sema_kit => unreachable,
3494 .eager => unreachable,
3495 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3496 },
3497 };
34823498
34833499 var size: u64 = 0;
34843500 if (code_align > payload_align) {
test/behavior.zig+1
......@@ -98,6 +98,7 @@ test {
9898 _ = @import("behavior/bugs/12911.zig");
9999 _ = @import("behavior/bugs/12928.zig");
100100 _ = @import("behavior/bugs/12945.zig");
101 _ = @import("behavior/bugs/12984.zig");
101102 _ = @import("behavior/byteswap.zig");
102103 _ = @import("behavior/byval_arg_var.zig");
103104 _ = @import("behavior/call.zig");
test/behavior/bugs/12984.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn DeleagateWithContext(comptime Function: type) type {
5 const ArgArgs = std.meta.ArgsTuple(Function);
6 return struct {
7 t: ArgArgs,
8 };
9}
10
11pub const OnConfirm = DeleagateWithContext(fn (bool) void);
12pub const CustomDraw = DeleagateWithContext(fn (?OnConfirm) void);
13
14test "simple test" {
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
19
20 var c: CustomDraw = undefined;
21 _ = c;
22}