mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
compiler: fix comptime memory store bugs
* 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: #23307
This commit is contained in:
parent
87983e800a
commit
db936b9094
3 changed files with 73 additions and 4 deletions
|
|
@ -65,6 +65,15 @@ pub fn storeComptimePtr(
|
|||
const zcu = pt.zcu;
|
||||
const ptr_info = ptr.typeOf(zcu).ptrInfo(zcu);
|
||||
assert(store_val.typeOf(zcu).toIntern() == ptr_info.child);
|
||||
|
||||
{
|
||||
const store_ty: Type = .fromInterned(ptr_info.child);
|
||||
if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) {
|
||||
// zero-bit store; nothing to do
|
||||
return .success;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: host size for vectors is terrible
|
||||
const host_bits = switch (ptr_info.flags.vector_index) {
|
||||
.none => ptr_info.packed_offset.host_size * 8,
|
||||
|
|
|
|||
|
|
@ -1740,10 +1740,7 @@ pub fn bitSizeInner(
|
|||
const len = array_type.lenIncludingSentinel();
|
||||
if (len == 0) return 0;
|
||||
const elem_ty = Type.fromInterned(array_type.child);
|
||||
const elem_size = @max(
|
||||
(try elem_ty.abiAlignmentInner(strat_lazy, zcu, tid)).scalar.toByteUnits() orelse 0,
|
||||
(try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar,
|
||||
);
|
||||
const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar;
|
||||
if (elem_size == 0) return 0;
|
||||
const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
|
||||
return (len - 1) * 8 * elem_size + elem_bit_size;
|
||||
|
|
|
|||
|
|
@ -515,3 +515,66 @@ fn fieldPtrTest() u32 {
|
|||
test "pointer in aggregate field can mutate comptime state" {
|
||||
try comptime std.testing.expect(fieldPtrTest() == 2);
|
||||
}
|
||||
|
||||
test "comptime store of extern struct with void field" {
|
||||
comptime {
|
||||
var x: extern struct { a: u8, b: void } = undefined;
|
||||
x = .{ .a = 123, .b = {} };
|
||||
std.debug.assert(x.a == 123);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime store of extern struct with void field into array" {
|
||||
comptime {
|
||||
var x: [3]extern struct { a: u8, b: void } = undefined;
|
||||
x[1] = .{ .a = 123, .b = {} };
|
||||
std.debug.assert(x[1].a == 123);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime store of packed struct with void field" {
|
||||
comptime {
|
||||
var x: packed struct { a: u8, b: void } = undefined;
|
||||
x = .{ .a = 123, .b = {} };
|
||||
std.debug.assert(x.a == 123);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime store of packed struct with void field into array" {
|
||||
comptime {
|
||||
var x: [3]packed struct { a: u8, b: void } = undefined;
|
||||
x[1] = .{ .a = 123, .b = {} };
|
||||
std.debug.assert(x[1].a == 123);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime store of reinterpreted zero-bit type" {
|
||||
const S = struct {
|
||||
fn doTheTest(comptime T: type) void {
|
||||
comptime var buf: T = undefined;
|
||||
const ptr: *void = @ptrCast(&buf);
|
||||
ptr.* = {};
|
||||
}
|
||||
};
|
||||
S.doTheTest(void);
|
||||
S.doTheTest(u0);
|
||||
S.doTheTest([0]u8);
|
||||
S.doTheTest([1]u0);
|
||||
S.doTheTest([5]u0);
|
||||
S.doTheTest([5]void);
|
||||
S.doTheTest(packed struct(u0) {});
|
||||
}
|
||||
|
||||
test "comptime store to extern struct reinterpreted as byte array" {
|
||||
const T = extern struct {
|
||||
x: u32,
|
||||
y: f32,
|
||||
z: [2]void,
|
||||
};
|
||||
comptime var val: T = undefined;
|
||||
|
||||
const bytes: *[@sizeOf(T)]u8 = @ptrCast(&val);
|
||||
@memset(bytes, 0);
|
||||
|
||||
comptime std.debug.assert(val.x == 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue