authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-08-27 17:28:37+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-28 12:33:36-07:00
logb8e6c426887e92cc5a841a7dd58eb10ebfbe0d77
treebda2f894bffbc95f62920f94121bf0f4e33cfae5
parent8d036d1d78bd6db5fd39b30c6182196c1e49a3db

compiler: provide result type for @memset value

Resolves: #16986

5 files changed, 49 insertions(+), 2 deletions(-)

src/AstGen.zig+6-2
...@@ -2441,6 +2441,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2441,6 +2441,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2441 .array_type_sentinel,2441 .array_type_sentinel,
2442 .elem_type_index,2442 .elem_type_index,
2443 .elem_type,2443 .elem_type,
2444 .indexable_ptr_elem_type,
2444 .vector_elem_type,2445 .vector_elem_type,
2445 .vector_type,2446 .vector_type,
2446 .indexable_ptr_len,2447 .indexable_ptr_len,
...@@ -8302,9 +8303,12 @@ fn builtinCall(...@@ -8302,9 +8303,12 @@ fn builtinCall(
8302 return rvalue(gz, ri, .void_value, node);8303 return rvalue(gz, ri, .void_value, node);
8303 },8304 },
8304 .memset => {8305 .memset => {
8306 const lhs = try expr(gz, scope, .{ .rl = .none }, params[0]);
8307 const lhs_ty = try gz.addUnNode(.typeof, lhs, params[0]);
8308 const elem_ty = try gz.addUnNode(.indexable_ptr_elem_type, lhs_ty, params[0]);
8305 _ = try gz.addPlNode(.memset, node, Zir.Inst.Bin{8309 _ = try gz.addPlNode(.memset, node, Zir.Inst.Bin{
8306 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),8310 .lhs = lhs,
8307 .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]),8311 .rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = elem_ty } }, params[1]),
8308 });8312 });
8309 return rvalue(gz, ri, .void_value, node);8313 return rvalue(gz, ri, .void_value, node);
8310 },8314 },
src/Sema.zig+17
...@@ -1023,6 +1023,7 @@ fn analyzeBodyInner(...@@ -1023,6 +1023,7 @@ fn analyzeBodyInner(
1023 .elem_val_node => try sema.zirElemValNode(block, inst),1023 .elem_val_node => try sema.zirElemValNode(block, inst),
1024 .elem_type_index => try sema.zirElemTypeIndex(block, inst),1024 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
1025 .elem_type => try sema.zirElemType(block, inst),1025 .elem_type => try sema.zirElemType(block, inst),
1026 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),
1026 .vector_elem_type => try sema.zirVectorElemType(block, inst),1027 .vector_elem_type => try sema.zirVectorElemType(block, inst),
1027 .enum_literal => try sema.zirEnumLiteral(block, inst),1028 .enum_literal => try sema.zirEnumLiteral(block, inst),
1028 .int_from_enum => try sema.zirIntFromEnum(block, inst),1029 .int_from_enum => try sema.zirIntFromEnum(block, inst),
...@@ -8106,6 +8107,22 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -8106,6 +8107,22 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
8106 return Air.internedToRef(ptr_ty.childType(mod).toIntern());8107 return Air.internedToRef(ptr_ty.childType(mod).toIntern());
8107}8108}
81088109
8110fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8111 const mod = sema.mod;
8112 const un_node = sema.code.instructions.items(.data)[inst].un_node;
8113 const src = un_node.src();
8114 const ptr_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {
8115 error.GenericPoison => return .generic_poison_type,
8116 else => |e| return e,
8117 };
8118 try sema.checkMemOperand(block, src, ptr_ty);
8119 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
8120 .Slice, .Many, .C => ptr_ty.childType(mod),
8121 .One => ptr_ty.childType(mod).childType(mod),
8122 };
8123 return Air.internedToRef(elem_ty.toIntern());
8124}
8125
8109fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8126fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8110 const mod = sema.mod;8127 const mod = sema.mod;
8111 const un_node = sema.code.instructions.items(.data)[inst].un_node;8128 const un_node = sema.code.instructions.items(.data)[inst].un_node;
src/Zir.zig+7
...@@ -248,6 +248,10 @@ pub const Inst = struct {...@@ -248,6 +248,10 @@ pub const Inst = struct {
248 /// Given a pointer type, returns its element type.248 /// Given a pointer type, returns its element type.
249 /// Uses the `un_node` field.249 /// Uses the `un_node` field.
250 elem_type,250 elem_type,
251 /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its
252 /// element type. Emits a compile error if the type is not an indexable pointer.
253 /// Uses the `un_node` field.
254 indexable_ptr_elem_type,
251 /// Given a vector type, returns its element type.255 /// Given a vector type, returns its element type.
252 /// Uses the `un_node` field.256 /// Uses the `un_node` field.
253 vector_elem_type,257 vector_elem_type,
...@@ -1021,6 +1025,7 @@ pub const Inst = struct {...@@ -1021,6 +1025,7 @@ pub const Inst = struct {
1021 .vector_type,1025 .vector_type,
1022 .elem_type_index,1026 .elem_type_index,
1023 .elem_type,1027 .elem_type,
1028 .indexable_ptr_elem_type,
1024 .vector_elem_type,1029 .vector_elem_type,
1025 .indexable_ptr_len,1030 .indexable_ptr_len,
1026 .anyframe_type,1031 .anyframe_type,
...@@ -1325,6 +1330,7 @@ pub const Inst = struct {...@@ -1325,6 +1330,7 @@ pub const Inst = struct {
1325 .vector_type,1330 .vector_type,
1326 .elem_type_index,1331 .elem_type_index,
1327 .elem_type,1332 .elem_type,
1333 .indexable_ptr_elem_type,
1328 .vector_elem_type,1334 .vector_elem_type,
1329 .indexable_ptr_len,1335 .indexable_ptr_len,
1330 .anyframe_type,1336 .anyframe_type,
...@@ -1557,6 +1563,7 @@ pub const Inst = struct {...@@ -1557,6 +1563,7 @@ pub const Inst = struct {
1557 .vector_type = .pl_node,1563 .vector_type = .pl_node,
1558 .elem_type_index = .bin,1564 .elem_type_index = .bin,
1559 .elem_type = .un_node,1565 .elem_type = .un_node,
1566 .indexable_ptr_elem_type = .un_node,
1560 .vector_elem_type = .un_node,1567 .vector_elem_type = .un_node,
1561 .indexable_ptr_len = .un_node,1568 .indexable_ptr_len = .un_node,
1562 .anyframe_type = .un_node,1569 .anyframe_type = .un_node,
src/print_zir.zig+1
...@@ -154,6 +154,7 @@ const Writer = struct {...@@ -154,6 +154,7 @@ const Writer = struct {
154 .alloc_mut,154 .alloc_mut,
155 .alloc_comptime_mut,155 .alloc_comptime_mut,
156 .elem_type,156 .elem_type,
157 .indexable_ptr_elem_type,
157 .vector_elem_type,158 .vector_elem_type,
158 .indexable_ptr_len,159 .indexable_ptr_len,
159 .anyframe_type,160 .anyframe_type,
test/behavior/memset.zig+18
...@@ -135,3 +135,21 @@ test "memset with large array element, comptime known" {...@@ -135,3 +135,21 @@ test "memset with large array element, comptime known" {
135 for (buf[3]) |elem| try expect(elem == 0);135 for (buf[3]) |elem| try expect(elem == 0);
136 for (buf[4]) |elem| try expect(elem == 0);136 for (buf[4]) |elem| try expect(elem == 0);
137}137}
138
139test "@memset provides result type" {
140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
144
145 const S = struct { x: u32 };
146
147 var buf1: [5]S = undefined;
148 @memset(&buf1, .{ .x = @intCast(12) });
149
150 var buf2: [5]S = undefined;
151 @memset(@as([]S, &buf2), .{ .x = @intCast(34) });
152
153 for (buf1) |s| try expect(s.x == 12);
154 for (buf2) |s| try expect(s.x == 34);
155}