diff --git a/src/AstGen.zig b/src/AstGen.zig index 80f7017ecc..6c4e546806 100644 --- 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 index 09e13664ea..a0af64fc83 100644 --- 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 index 5b149d02d9..dd9bdc12a2 100644 --- 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 index 86f4a45e29..33de432522 100644 --- 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 index 32d9cf1eb8..e3cf646f87 100644 --- 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); +}