stage2: Fix panic on initializing comptime fields in tuple

This resolves https://github.com/ziglang/zig/issues/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.
This commit is contained in:
Cody Tapscott 2022-03-15 14:00:33 -07:00 committed by Andrew Kelley
parent 762c4a876b
commit 480e7eec65
6 changed files with 62 additions and 8 deletions

View File

@ -3203,11 +3203,6 @@ fn zirValidateArrayInit(
// Determine whether the value stored to this pointer is comptime-known.
if (opt_opv) |opv| {
element_vals[i] = opv;
continue;
}
const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
// Find the block index of the elem_ptr so that we can look at the next
@ -3223,6 +3218,12 @@ fn zirValidateArrayInit(
break :inst block.instructions.items[block_index + 1];
};
// Array has one possible value, so value is always comptime-known
if (opt_opv) |opv| {
element_vals[i] = opv;
continue;
}
// If the next instructon is a store with a comptime operand, this element
// is comptime.
switch (air_tags[next_air_inst]) {

View File

@ -5422,21 +5422,22 @@ pub const FuncGen = struct {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const dest_ptr = try self.resolveInst(bin_op.lhs);
const ptr_ty = self.air.typeOf(bin_op.lhs);
const operand_ty = ptr_ty.childType();
if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;
// TODO Sema should emit a different instruction when the store should
// possibly do the safety 0xaa bytes for undefined.
const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
if (val_is_undef) {
const elem_ty = ptr_ty.childType();
const target = self.dg.module.getTarget();
const elem_size = elem_ty.abiSize(target);
const operand_size = operand_ty.abiSize(target);
const u8_llvm_ty = self.context.intType(8);
const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0);
const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, "");
const fill_char = u8_llvm_ty.constInt(0xaa, .False);
const dest_ptr_align = ptr_ty.ptrAlignment(target);
const usize_llvm_ty = try self.dg.llvmType(Type.usize);
const len = usize_llvm_ty.constInt(elem_size, .False);
const len = usize_llvm_ty.constInt(operand_size, .False);
_ = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align, ptr_ty.isVolatilePtr());
if (self.dg.module.comp.bin_file.options.valgrind) {
// TODO generate valgrind client request to mark byte range as undefined

View File

@ -65,8 +65,11 @@ test {
_ = @import("behavior/bugs/10970.zig");
_ = @import("behavior/bugs/11046.zig");
_ = @import("behavior/bugs/11139.zig");
_ = @import("behavior/bugs/11159.zig");
_ = @import("behavior/bugs/11162.zig");
_ = @import("behavior/bugs/11165.zig");
_ = @import("behavior/bugs/11181.zig");
_ = @import("behavior/bugs/11182.zig");
_ = @import("behavior/call.zig");
_ = @import("behavior/cast.zig");
_ = @import("behavior/comptime_memory.zig");

View File

@ -0,0 +1,23 @@
const std = @import("std");
const builtin = @import("builtin");
test {
const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
var a: T = .{ 0, 0 };
_ = a;
}
test {
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
const S = struct {
comptime x: i32 = 0,
comptime y: u32 = 0,
};
var a: S = .{};
_ = a;
var b = S{};
_ = b;
}

View File

@ -0,0 +1,16 @@
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;
test {
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
var x: u32 = 15;
const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
var a: T = .{ -1234, 5678, x + 1 };
try expect(a[0] == -1234);
try expect(a[1] == 5678);
try expect(a[2] == 16);
}

View File

@ -0,0 +1,10 @@
const std = @import("std");
const builtin = @import("builtin");
test {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const T = @TypeOf(.{ @as(i32, 0), @as(u32, 0) });
var a = T{ 0, 0 };
_ = a;
}