authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-07-29 06:22:29+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-08-09 19:46:58+01:00
log93e53d1e00793d769d4ee39b3cbfd0c88257687d
tree615f4e4fa503210282bd0bdf313ff1f7210bceb0
parent6917a8c25824d12f00327171b583d6cd9a830c29
signaturelock-open Commit is signed but in an unrecognized format.

compiler: fix crash on invalid result type for `@splat`

This introduces a new ZIR instruction, `vec_elem_type`. Co-Authored-By: Ali Chraghi <alichraghi@proton.me> Resolves: #16567

5 files changed, 36 insertions(+), 7 deletions(-)

src/AstGen.zig+2-7
...@@ -2569,6 +2569,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2569,6 +2569,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2569 .array_type_sentinel,2569 .array_type_sentinel,
2570 .elem_type_index,2570 .elem_type_index,
2571 .elem_type,2571 .elem_type,
2572 .vector_elem_type,
2572 .vector_type,2573 .vector_type,
2573 .indexable_ptr_len,2574 .indexable_ptr_len,
2574 .anyframe_type,2575 .anyframe_type,
...@@ -8624,13 +8625,7 @@ fn builtinCall(...@@ -8624,13 +8625,7 @@ fn builtinCall(
86248625
8625 .splat => {8626 .splat => {
8626 const result_type = try ri.rl.resultType(gz, node, "@splat");8627 const result_type = try ri.rl.resultType(gz, node, "@splat");
8627 const elem_type = try gz.add(.{8628 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
8628 .tag = .elem_type_index,
8629 .data = .{ .bin = .{
8630 .lhs = result_type,
8631 .rhs = @as(Zir.Inst.Ref, @enumFromInt(0)),
8632 } },
8633 });
8634 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);8629 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
8635 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{8630 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
8636 .lhs = result_type,8631 .lhs = result_type,
src/Sema.zig+18
...@@ -1022,6 +1022,7 @@ fn analyzeBodyInner(...@@ -1022,6 +1022,7 @@ fn analyzeBodyInner(
1022 .elem_val_node => try sema.zirElemValNode(block, inst),1022 .elem_val_node => try sema.zirElemValNode(block, inst),
1023 .elem_type_index => try sema.zirElemTypeIndex(block, inst),1023 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
1024 .elem_type => try sema.zirElemType(block, inst),1024 .elem_type => try sema.zirElemType(block, inst),
1025 .vector_elem_type => try sema.zirVectorElemType(block, inst),
1025 .enum_literal => try sema.zirEnumLiteral(block, inst),1026 .enum_literal => try sema.zirEnumLiteral(block, inst),
1026 .int_from_enum => try sema.zirIntFromEnum(block, inst),1027 .int_from_enum => try sema.zirIntFromEnum(block, inst),
1027 .enum_from_int => try sema.zirEnumFromInt(block, inst),1028 .enum_from_int => try sema.zirEnumFromInt(block, inst),
...@@ -7804,6 +7805,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -7804,6 +7805,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
7804 return sema.addType(ptr_ty.childType(mod));7805 return sema.addType(ptr_ty.childType(mod));
7805}7806}
78067807
7808fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7809 const mod = sema.mod;
7810 const un_node = sema.code.instructions.items(.data)[inst].un_node;
7811 const vec_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) {
7812 // Since this is a ZIR instruction that returns a type, encountering
7813 // generic poison should not result in a failed compilation, but the
7814 // generic poison type. This prevents unnecessary failures when
7815 // constructing types at compile-time.
7816 error.GenericPoison => return .generic_poison_type,
7817 else => |e| return e,
7818 };
7819 if (!vec_ty.isVector(mod)) {
7820 return sema.fail(block, un_node.src(), "expected vector type, found '{}'", .{vec_ty.fmt(mod)});
7821 }
7822 return sema.addType(vec_ty.childType(mod));
7823}
7824
7807fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7825fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7808 const mod = sema.mod;7826 const mod = sema.mod;
7809 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;7827 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
src/Zir.zig+6
...@@ -248,6 +248,9 @@ pub const Inst = struct {...@@ -248,6 +248,9 @@ 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 a vector type, returns its element type.
252 /// Uses the `un_node` field.
253 vector_elem_type,
251 /// Given a pointer to an indexable object, returns the len property. This is254 /// Given a pointer to an indexable object, returns the len property. This is
252 /// used by for loops. This instruction also emits a for-loop specific compile255 /// used by for loops. This instruction also emits a for-loop specific compile
253 /// error if the indexable object is not indexable.256 /// error if the indexable object is not indexable.
...@@ -1029,6 +1032,7 @@ pub const Inst = struct {...@@ -1029,6 +1032,7 @@ pub const Inst = struct {
1029 .vector_type,1032 .vector_type,
1030 .elem_type_index,1033 .elem_type_index,
1031 .elem_type,1034 .elem_type,
1035 .vector_elem_type,
1032 .indexable_ptr_len,1036 .indexable_ptr_len,
1033 .anyframe_type,1037 .anyframe_type,
1034 .as,1038 .as,
...@@ -1334,6 +1338,7 @@ pub const Inst = struct {...@@ -1334,6 +1338,7 @@ pub const Inst = struct {
1334 .vector_type,1338 .vector_type,
1335 .elem_type_index,1339 .elem_type_index,
1336 .elem_type,1340 .elem_type,
1341 .vector_elem_type,
1337 .indexable_ptr_len,1342 .indexable_ptr_len,
1338 .anyframe_type,1343 .anyframe_type,
1339 .as,1344 .as,
...@@ -1565,6 +1570,7 @@ pub const Inst = struct {...@@ -1565,6 +1570,7 @@ pub const Inst = struct {
1565 .vector_type = .pl_node,1570 .vector_type = .pl_node,
1566 .elem_type_index = .bin,1571 .elem_type_index = .bin,
1567 .elem_type = .un_node,1572 .elem_type = .un_node,
1573 .vector_elem_type = .un_node,
1568 .indexable_ptr_len = .un_node,1574 .indexable_ptr_len = .un_node,
1569 .anyframe_type = .un_node,1575 .anyframe_type = .un_node,
1570 .as = .bin,1576 .as = .bin,
src/print_zir.zig+1
...@@ -155,6 +155,7 @@ const Writer = struct {...@@ -155,6 +155,7 @@ const Writer = struct {
155 .alloc_mut,155 .alloc_mut,
156 .alloc_comptime_mut,156 .alloc_comptime_mut,
157 .elem_type,157 .elem_type,
158 .vector_elem_type,
158 .indexable_ptr_len,159 .indexable_ptr_len,
159 .anyframe_type,160 .anyframe_type,
160 .bit_not,161 .bit_not,
test/cases/compile_errors/splat_result_type_non_vector.zig created+9
...@@ -0,0 +1,9 @@
1export fn f() void {
2 _ = @as(u32, @splat(5));
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:18: error: expected vector type, found 'u32'