From ffa6f895fff52846bc4b82cc9b449d0f7224d7d9 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 13 Jun 2022 11:40:20 +0300 Subject: [PATCH 1/4] Sema: validateArrayInit detect bitcast before store --- src/Sema.zig | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index a769194776..af3e824855 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3795,6 +3795,32 @@ fn zirValidateArrayInit( } continue; }, + .bitcast => { + // %a = bitcast(*arr_ty, %array_base) + // %b = ptr_elem_ptr(%a, %index) + // %c = bitcast(*elem_ty, %b) + // %d = store(%c, %val) + if (air_datas[next_air_inst].ty_op.operand != elem_ptr_air_ref) { + array_is_comptime = false; + continue; + } + const store_inst = block.instructions.items[block_index + 2]; + if (air_tags[store_inst] != .store) { + array_is_comptime = false; + continue; + } + const bin_op = air_datas[store_inst].bin_op; + if (bin_op.lhs != Air.indexToRef(next_air_inst)) { + array_is_comptime = false; + continue; + } + if (try sema.resolveMaybeUndefValAllowVariables(block, elem_src, bin_op.rhs)) |val| { + element_vals[i] = val; + } else { + array_is_comptime = false; + } + continue; + }, else => { array_is_comptime = false; continue; From b9dcbe6b4c0bee37b31bf46424f284af331d4696 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 15 Jun 2022 18:00:29 +0300 Subject: [PATCH 2/4] Sema: handle sentinels in tupleToArray --- src/Sema.zig | 12 +++++++++--- test/behavior/array.zig | 11 +++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index af3e824855..1d5342b841 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21793,7 +21793,7 @@ fn coerceTupleToArray( ) !Air.Inst.Ref { const inst_ty = sema.typeOf(inst); const inst_len = inst_ty.arrayLen(); - const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen()); + const dest_len = dest_ty.arrayLen(); if (dest_len != inst_len) { const msg = msg: { @@ -21808,13 +21808,19 @@ fn coerceTupleToArray( return sema.failWithOwnedErrorMsg(block, msg); } - const element_vals = try sema.arena.alloc(Value, dest_len); - const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len); + const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLenIncludingSentinel()); + const element_vals = try sema.arena.alloc(Value, dest_elems); + const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems); const dest_elem_ty = dest_ty.childType(); var runtime_src: ?LazySrcLoc = null; for (element_vals) |*elem, i_usize| { const i = @intCast(u32, i_usize); + if (i_usize == inst_len) { + elem.* = dest_ty.sentinel().?; + element_refs[i] = try sema.addConstant(dest_elem_ty, elem.*); + break; + } const elem_src = inst_src; // TODO better source location const elem_ref = try tupleField(sema, block, inst_src, inst, elem_src, i); const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src); diff --git a/test/behavior/array.zig b/test/behavior/array.zig index bccff1edf0..6482bfa1fe 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -582,3 +582,14 @@ test "array with comptime only element type" { try testing.expect(a[0] == u32); try testing.expect(a[1] == i32); } + +test "tuple to array handles sentinel" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + const a = .{ 1, 2, 3 }; + var b: [3:0]u8 = a; + }; + try expect(S.b[0] == 1); +} From a224dfceee07a94d961506122a434563129428a5 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 15 Jun 2022 18:34:56 +0300 Subject: [PATCH 3/4] std.tz: fix function returning pointer to local variable --- lib/std/tz.zig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/std/tz.zig b/lib/std/tz.zig index cea845e148..76eb3b06fc 100644 --- a/lib/std/tz.zig +++ b/lib/std/tz.zig @@ -11,7 +11,7 @@ pub const Timetype = struct { flags: u8, name_data: [6:0]u8, - pub fn name(self: Timetype) [:0]const u8 { + pub fn name(self: *const Timetype) [:0]const u8 { return std.mem.sliceTo(self.name_data[0..], 0); } @@ -214,7 +214,6 @@ pub const Tz = struct { }; test "slim" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO const data = @embedFile("tz/asia_tokyo.tzif"); var in_stream = std.io.fixedBufferStream(data); @@ -228,7 +227,6 @@ test "slim" { } test "fat" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO const data = @embedFile("tz/antarctica_davis.tzif"); var in_stream = std.io.fixedBufferStream(data); @@ -241,7 +239,6 @@ test "fat" { } test "legacy" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO // Taken from Slackware 8.0, from 2001 const data = @embedFile("tz/europe_vatican.tzif"); var in_stream = std.io.fixedBufferStream(data); From 28986a059075c2dce662c2f4e823b3efd283df87 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 17 Jun 2022 18:53:40 +0300 Subject: [PATCH 4/4] stage2: check that struct is a tuple when value tags differ in eql --- lib/std/bit_set.zig | 4 ---- src/value.zig | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index 9b0079ec74..8006a623b5 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -1330,7 +1330,6 @@ fn testStaticBitSet(comptime Set: type) !void { } test "IntegerBitSet" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO try testStaticBitSet(IntegerBitSet(0)); try testStaticBitSet(IntegerBitSet(1)); try testStaticBitSet(IntegerBitSet(2)); @@ -1342,7 +1341,6 @@ test "IntegerBitSet" { } test "ArrayBitSet" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO if (@import("builtin").cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/9879 return error.SkipZigTest; @@ -1357,7 +1355,6 @@ test "ArrayBitSet" { } test "DynamicBitSetUnmanaged" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO const allocator = std.testing.allocator; var a = try DynamicBitSetUnmanaged.initEmpty(allocator, 300); try testing.expectEqual(@as(usize, 0), a.count()); @@ -1398,7 +1395,6 @@ test "DynamicBitSetUnmanaged" { } test "DynamicBitSet" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO const allocator = std.testing.allocator; var a = try DynamicBitSet.initEmpty(allocator, 300); try testing.expectEqual(@as(usize, 0), a.count()); diff --git a/src/value.zig b/src/value.zig index 996aa76bf5..2239bb7b0e 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2186,7 +2186,7 @@ pub const Value = extern union { // A tuple can be represented with .empty_struct_value, // the_one_possible_value, .aggregate in which case we could // end up here and the values are equal if the type has zero fields. - return ty.structFieldCount() != 0; + return ty.isTupleOrAnonStruct() and ty.structFieldCount() != 0; }, .Float => { const a_nan = a.isNan();