Skip to content

Commit 480e7ee

Browse files
topolarityandrewrk
authored andcommitted
stage2: Fix panic on initializing comptime fields in tuple
This resolves ziglang#11159 The problem was that: 1. We were not correctly deleting the field stores after recognizing that an array initializer was a comptime-known value. 2. LLVM was not checking that the final type had no runtime bits, and so would generate an invalid store. This also adds several test cases for related bugs, just to check these in for later work.
1 parent 762c4a8 commit 480e7ee

File tree

6 files changed

+62
-8
lines changed

6 files changed

+62
-8
lines changed

src/Sema.zig

+6-5
Original file line numberDiff line numberDiff line change
@@ -3203,11 +3203,6 @@ fn zirValidateArrayInit(
32033203

32043204
// Determine whether the value stored to this pointer is comptime-known.
32053205

3206-
if (opt_opv) |opv| {
3207-
element_vals[i] = opv;
3208-
continue;
3209-
}
3210-
32113206
const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
32123207
const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
32133208
// Find the block index of the elem_ptr so that we can look at the next
@@ -3223,6 +3218,12 @@ fn zirValidateArrayInit(
32233218
break :inst block.instructions.items[block_index + 1];
32243219
};
32253220

3221+
// Array has one possible value, so value is always comptime-known
3222+
if (opt_opv) |opv| {
3223+
element_vals[i] = opv;
3224+
continue;
3225+
}
3226+
32263227
// If the next instructon is a store with a comptime operand, this element
32273228
// is comptime.
32283229
switch (air_tags[next_air_inst]) {

src/codegen/llvm.zig

+4-3
Original file line numberDiff line numberDiff line change
@@ -5422,21 +5422,22 @@ pub const FuncGen = struct {
54225422
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
54235423
const dest_ptr = try self.resolveInst(bin_op.lhs);
54245424
const ptr_ty = self.air.typeOf(bin_op.lhs);
5425+
const operand_ty = ptr_ty.childType();
5426+
if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;
54255427

54265428
// TODO Sema should emit a different instruction when the store should
54275429
// possibly do the safety 0xaa bytes for undefined.
54285430
const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
54295431
if (val_is_undef) {
5430-
const elem_ty = ptr_ty.childType();
54315432
const target = self.dg.module.getTarget();
5432-
const elem_size = elem_ty.abiSize(target);
5433+
const operand_size = operand_ty.abiSize(target);
54335434
const u8_llvm_ty = self.context.intType(8);
54345435
const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0);
54355436
const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, "");
54365437
const fill_char = u8_llvm_ty.constInt(0xaa, .False);
54375438
const dest_ptr_align = ptr_ty.ptrAlignment(target);
54385439
const usize_llvm_ty = try self.dg.llvmType(Type.usize);
5439-
const len = usize_llvm_ty.constInt(elem_size, .False);
5440+
const len = usize_llvm_ty.constInt(operand_size, .False);
54405441
_ = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());
54415442
if (self.dg.module.comp.bin_file.options.valgrind) {
54425443
// TODO generate valgrind client request to mark byte range as undefined

test/behavior.zig

+3
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@ test {
6565
_ = @import("behavior/bugs/10970.zig");
6666
_ = @import("behavior/bugs/11046.zig");
6767
_ = @import("behavior/bugs/11139.zig");
68+
_ = @import("behavior/bugs/11159.zig");
69+
_ = @import("behavior/bugs/11162.zig");
6870
_ = @import("behavior/bugs/11165.zig");
6971
_ = @import("behavior/bugs/11181.zig");
72+
_ = @import("behavior/bugs/11182.zig");
7073
_ = @import("behavior/call.zig");
7174
_ = @import("behavior/cast.zig");
7275
_ = @import("behavior/comptime_memory.zig");

test/behavior/bugs/11159.zig

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const std = @import("std");
2+
const builtin = @import("builtin");
3+
4+
test {
5+
const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
6+
var a: T = .{ 0, 0 };
7+
_ = a;
8+
}
9+
10+
test {
11+
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
12+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14+
15+
const S = struct {
16+
comptime x: i32 = 0,
17+
comptime y: u32 = 0,
18+
};
19+
var a: S = .{};
20+
_ = a;
21+
var b = S{};
22+
_ = b;
23+
}

test/behavior/bugs/11162.zig

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const std = @import("std");
2+
const builtin = @import("builtin");
3+
const expect = std.testing.expect;
4+
5+
test {
6+
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
7+
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
8+
9+
var x: u32 = 15;
10+
const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
11+
var a: T = .{ -1234, 5678, x + 1 };
12+
13+
try expect(a[0] == -1234);
14+
try expect(a[1] == 5678);
15+
try expect(a[2] == 16);
16+
}

test/behavior/bugs/11182.zig

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const std = @import("std");
2+
const builtin = @import("builtin");
3+
4+
test {
5+
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
6+
7+
const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
8+
var a = T{ 0, 0 };
9+
_ = a;
10+
}

0 commit comments

Comments
 (0)