motiejus/zig

fork of https://codeberg.org/ziglang/zig
git clone https://git.jakstys.lt/motiejus/zig.git
Log | Tree | Refs | README | LICENSE

commit b8e6c426887e92cc5a841a7dd58eb10ebfbe0d77 (tree)
parent 8d036d1d78bd6db5fd39b30c6182196c1e49a3db
Author: mlugg <mlugg@mlugg.co.uk>
Date:   Sun, 27 Aug 2023 17:28:37 +0100

compiler: provide result type for @memset value

Resolves: #16986

Diffstat:
Msrc/AstGen.zig | 8++++++--
Msrc/Sema.zig | 17+++++++++++++++++
Msrc/Zir.zig | 7+++++++
Msrc/print_zir.zig | 1+
Mtest/behavior/memset.zig | 18++++++++++++++++++
5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/src/AstGen.zig b/src/AstGen.zig @@ -2441,6 +2441,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .array_type_sentinel, .elem_type_index, .elem_type, + .indexable_ptr_elem_type, .vector_elem_type, .vector_type, .indexable_ptr_len, @@ -8302,9 +8303,12 @@ fn builtinCall( return rvalue(gz, ri, .void_value, node); }, .memset => { + const lhs = try expr(gz, scope, .{ .rl = .none }, params[0]); + const lhs_ty = try gz.addUnNode(.typeof, lhs, params[0]); + const elem_ty = try gz.addUnNode(.indexable_ptr_elem_type, lhs_ty, params[0]); _ = try gz.addPlNode(.memset, node, Zir.Inst.Bin{ - .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]), - .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), + .lhs = lhs, + .rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = elem_ty } }, params[1]), }); return rvalue(gz, ri, .void_value, node); }, diff --git a/src/Sema.zig b/src/Sema.zig @@ -1023,6 +1023,7 @@ fn analyzeBodyInner( .elem_val_node => try sema.zirElemValNode(block, inst), .elem_type_index => try sema.zirElemTypeIndex(block, inst), .elem_type => try sema.zirElemType(block, inst), + .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst), .vector_elem_type => try sema.zirVectorElemType(block, inst), .enum_literal => try sema.zirEnumLiteral(block, inst), .int_from_enum => try sema.zirIntFromEnum(block, inst), @@ -8106,6 +8107,22 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return Air.internedToRef(ptr_ty.childType(mod).toIntern()); } +fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const mod = sema.mod; + const un_node = sema.code.instructions.items(.data)[inst].un_node; + const src = un_node.src(); + const ptr_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) { + error.GenericPoison => return .generic_poison_type, + else => |e| return e, + }; + try sema.checkMemOperand(block, src, ptr_ty); + const elem_ty = switch (ptr_ty.ptrSize(mod)) { + .Slice, .Many, .C => ptr_ty.childType(mod), + .One => ptr_ty.childType(mod).childType(mod), + }; + return Air.internedToRef(elem_ty.toIntern()); +} + fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const un_node = sema.code.instructions.items(.data)[inst].un_node; diff --git a/src/Zir.zig b/src/Zir.zig @@ -248,6 +248,10 @@ pub const Inst = struct { /// Given a pointer type, returns its element type. /// Uses the `un_node` field. elem_type, + /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its + /// element type. Emits a compile error if the type is not an indexable pointer. + /// Uses the `un_node` field. + indexable_ptr_elem_type, /// Given a vector type, returns its element type. /// Uses the `un_node` field. vector_elem_type, @@ -1021,6 +1025,7 @@ pub const Inst = struct { .vector_type, .elem_type_index, .elem_type, + .indexable_ptr_elem_type, .vector_elem_type, .indexable_ptr_len, .anyframe_type, @@ -1325,6 +1330,7 @@ pub const Inst = struct { .vector_type, .elem_type_index, .elem_type, + .indexable_ptr_elem_type, .vector_elem_type, .indexable_ptr_len, .anyframe_type, @@ -1557,6 +1563,7 @@ pub const Inst = struct { .vector_type = .pl_node, .elem_type_index = .bin, .elem_type = .un_node, + .indexable_ptr_elem_type = .un_node, .vector_elem_type = .un_node, .indexable_ptr_len = .un_node, .anyframe_type = .un_node, diff --git a/src/print_zir.zig b/src/print_zir.zig @@ -154,6 +154,7 @@ const Writer = struct { .alloc_mut, .alloc_comptime_mut, .elem_type, + .indexable_ptr_elem_type, .vector_elem_type, .indexable_ptr_len, .anyframe_type, diff --git a/test/behavior/memset.zig b/test/behavior/memset.zig @@ -135,3 +135,21 @@ test "memset with large array element, comptime known" { for (buf[3]) |elem| try expect(elem == 0); for (buf[4]) |elem| try expect(elem == 0); } + +test "@memset provides result type" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + const S = struct { x: u32 }; + + var buf1: [5]S = undefined; + @memset(&buf1, .{ .x = @intCast(12) }); + + var buf2: [5]S = undefined; + @memset(@as([]S, &buf2), .{ .x = @intCast(34) }); + + for (buf1) |s| try expect(s.x == 12); + for (buf2) |s| try expect(s.x == 34); +}