| author | |
| committer | |
| log | db936b909471f5c7e0344489ab1e7d59ab387658 |
| tree | 733ceb4aaa6906ab70e1efab581a98b22bdfe50b |
| parent | 87983e800a2bd5a2369d49facb70e1a7854efeaa |
| signature |
* When storing a zero-bit type, we should short-circuit almost
immediately. Zero-bit stores do not need to do any work.
* The bit size computation for arrays is incorrect; the `abiSize` will
already be appropriately aligned, but the logic to do so here
incorrectly assumes that zero-bit types have an alignment of 0. They
don't; their alignment is 1.
Resolves: #21202
Resolves: #21508
Resolves: #233073 files changed, 73 insertions(+), 4 deletions(-)
src/Sema/comptime_ptr_access.zig+9| ... | ... | @@ -65,6 +65,15 @@ pub fn storeComptimePtr( |
| 65 | 65 | const zcu = pt.zcu; |
| 66 | 66 | const ptr_info = ptr.typeOf(zcu).ptrInfo(zcu); |
| 67 | 67 | assert(store_val.typeOf(zcu).toIntern() == ptr_info.child); |
| 68 | ||
| 69 | { | |
| 70 | const store_ty: Type = .fromInterned(ptr_info.child); | |
| 71 | if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) { | |
| 72 | // zero-bit store; nothing to do | |
| 73 | return .success; | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 68 | 77 | // TODO: host size for vectors is terrible |
| 69 | 78 | const host_bits = switch (ptr_info.flags.vector_index) { |
| 70 | 79 | .none => ptr_info.packed_offset.host_size * 8, |
src/Type.zig+1-4| ... | ... | @@ -1740,10 +1740,7 @@ pub fn bitSizeInner( |
| 1740 | 1740 | const len = array_type.lenIncludingSentinel(); |
| 1741 | 1741 | if (len == 0) return 0; |
| 1742 | 1742 | const elem_ty = Type.fromInterned(array_type.child); |
| 1743 | const elem_size = @max( | |
| 1744 | (try elem_ty.abiAlignmentInner(strat_lazy, zcu, tid)).scalar.toByteUnits() orelse 0, | |
| 1745 | (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar, | |
| 1746 | ); | |
| 1743 | const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar; | |
| 1747 | 1744 | if (elem_size == 0) return 0; |
| 1748 | 1745 | const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); |
| 1749 | 1746 | return (len - 1) * 8 * elem_size + elem_bit_size; |
test/behavior/comptime_memory.zig+63| ... | ... | @@ -515,3 +515,66 @@ fn fieldPtrTest() u32 { |
| 515 | 515 | test "pointer in aggregate field can mutate comptime state" { |
| 516 | 516 | try comptime std.testing.expect(fieldPtrTest() == 2); |
| 517 | 517 | } |
| 518 | ||
| 519 | test "comptime store of extern struct with void field" { | |
| 520 | comptime { | |
| 521 | var x: extern struct { a: u8, b: void } = undefined; | |
| 522 | x = .{ .a = 123, .b = {} }; | |
| 523 | std.debug.assert(x.a == 123); | |
| 524 | } | |
| 525 | } | |
| 526 | ||
| 527 | test "comptime store of extern struct with void field into array" { | |
| 528 | comptime { | |
| 529 | var x: [3]extern struct { a: u8, b: void } = undefined; | |
| 530 | x[1] = .{ .a = 123, .b = {} }; | |
| 531 | std.debug.assert(x[1].a == 123); | |
| 532 | } | |
| 533 | } | |
| 534 | ||
| 535 | test "comptime store of packed struct with void field" { | |
| 536 | comptime { | |
| 537 | var x: packed struct { a: u8, b: void } = undefined; | |
| 538 | x = .{ .a = 123, .b = {} }; | |
| 539 | std.debug.assert(x.a == 123); | |
| 540 | } | |
| 541 | } | |
| 542 | ||
| 543 | test "comptime store of packed struct with void field into array" { | |
| 544 | comptime { | |
| 545 | var x: [3]packed struct { a: u8, b: void } = undefined; | |
| 546 | x[1] = .{ .a = 123, .b = {} }; | |
| 547 | std.debug.assert(x[1].a == 123); | |
| 548 | } | |
| 549 | } | |
| 550 | ||
| 551 | test "comptime store of reinterpreted zero-bit type" { | |
| 552 | const S = struct { | |
| 553 | fn doTheTest(comptime T: type) void { | |
| 554 | comptime var buf: T = undefined; | |
| 555 | const ptr: *void = @ptrCast(&buf); | |
| 556 | ptr.* = {}; | |
| 557 | } | |
| 558 | }; | |
| 559 | S.doTheTest(void); | |
| 560 | S.doTheTest(u0); | |
| 561 | S.doTheTest([0]u8); | |
| 562 | S.doTheTest([1]u0); | |
| 563 | S.doTheTest([5]u0); | |
| 564 | S.doTheTest([5]void); | |
| 565 | S.doTheTest(packed struct(u0) {}); | |
| 566 | } | |
| 567 | ||
| 568 | test "comptime store to extern struct reinterpreted as byte array" { | |
| 569 | const T = extern struct { | |
| 570 | x: u32, | |
| 571 | y: f32, | |
| 572 | z: [2]void, | |
| 573 | }; | |
| 574 | comptime var val: T = undefined; | |
| 575 | ||
| 576 | const bytes: *[@sizeOf(T)]u8 = @ptrCast(&val); | |
| 577 | @memset(bytes, 0); | |
| 578 | ||
| 579 | comptime std.debug.assert(val.x == 0); | |
| 580 | } |