From 93e53d1e00793d769d4ee39b3cbfd0c88257687d Mon Sep 17 00:00:00 2001 From: mlugg Date: Sat, 29 Jul 2023 06:22:29 +0100 Subject: [PATCH] compiler: fix crash on invalid result type for `@splat` This introduces a new ZIR instruction, `vec_elem_type`. Co-Authored-By: Ali Chraghi Resolves: #16567 --- src/AstGen.zig | 9 ++------- src/Sema.zig | 18 ++++++++++++++++++ src/Zir.zig | 6 ++++++ src/print_zir.zig | 1 + .../splat_result_type_non_vector.zig | 9 +++++++++ 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 test/cases/compile_errors/splat_result_type_non_vector.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index 858b94622d14fae821532fd52e17da45ba93d30f..95287c0a3d4f5cf2cc67c63cacbc525f74c85d87 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2569,6 +2569,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .array_type_sentinel, .elem_type_index, .elem_type, + .vector_elem_type, .vector_type, .indexable_ptr_len, .anyframe_type, @@ -8624,13 +8625,7 @@ fn builtinCall( .splat => { const result_type = try ri.rl.resultType(gz, node, "@splat"); - const elem_type = try gz.add(.{ - .tag = .elem_type_index, - .data = .{ .bin = .{ - .lhs = result_type, - .rhs = @as(Zir.Inst.Ref, @enumFromInt(0)), - } }, - }); + const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node); const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ .lhs = result_type, diff --git a/src/Sema.zig b/src/Sema.zig index ab01d618e86146f364703793153007dc46151b7c..49dac7177e5ce208d881cb89e031064f12ce4edd 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1022,6 +1022,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), + .vector_elem_type => try sema.zirVectorElemType(block, inst), .enum_literal => try sema.zirEnumLiteral(block, inst), .int_from_enum => try sema.zirIntFromEnum(block, inst), .enum_from_int => try sema.zirEnumFromInt(block, inst), @@ -7804,6 +7805,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return sema.addType(ptr_ty.childType(mod)); } +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; + const vec_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) { + // Since this is a ZIR instruction that returns a type, encountering + // generic poison should not result in a failed compilation, but the + // generic poison type. This prevents unnecessary failures when + // constructing types at compile-time. + error.GenericPoison => return .generic_poison_type, + else => |e| return e, + }; + if (!vec_ty.isVector(mod)) { + return sema.fail(block, un_node.src(), "expected vector type, found '{}'", .{vec_ty.fmt(mod)}); + } + return sema.addType(vec_ty.childType(mod)); +} + fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].pl_node; diff --git a/src/Zir.zig b/src/Zir.zig index 9f7450fe5cc5b668e662375683120c66ea28d3b6..aa1945b236f4c003107dd8b4464f9fea2e716630 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -248,6 +248,9 @@ pub const Inst = struct { /// Given a pointer type, returns its element type. /// Uses the `un_node` field. elem_type, + /// Given a vector type, returns its element type. + /// Uses the `un_node` field. + vector_elem_type, /// Given a pointer to an indexable object, returns the len property. This is /// used by for loops. This instruction also emits a for-loop specific compile /// error if the indexable object is not indexable. @@ -1029,6 +1032,7 @@ pub const Inst = struct { .vector_type, .elem_type_index, .elem_type, + .vector_elem_type, .indexable_ptr_len, .anyframe_type, .as, @@ -1334,6 +1338,7 @@ pub const Inst = struct { .vector_type, .elem_type_index, .elem_type, + .vector_elem_type, .indexable_ptr_len, .anyframe_type, .as, @@ -1565,6 +1570,7 @@ pub const Inst = struct { .vector_type = .pl_node, .elem_type_index = .bin, .elem_type = .un_node, + .vector_elem_type = .un_node, .indexable_ptr_len = .un_node, .anyframe_type = .un_node, .as = .bin, diff --git a/src/print_zir.zig b/src/print_zir.zig index 7ed233a0c66180a8b6f7f37e11175b4eb67d4a51..3a158375ea3ca47ba3aa883332e5126dd4d9665d 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -155,6 +155,7 @@ const Writer = struct { .alloc_mut, .alloc_comptime_mut, .elem_type, + .vector_elem_type, .indexable_ptr_len, .anyframe_type, .bit_not, diff --git a/test/cases/compile_errors/splat_result_type_non_vector.zig b/test/cases/compile_errors/splat_result_type_non_vector.zig new file mode 100644 index 0000000000000000000000000000000000000000..dbff8dc041ff2b2be8180d7372954b901252700f --- /dev/null +++ b/test/cases/compile_errors/splat_result_type_non_vector.zig @@ -0,0 +1,9 @@ +export fn f() void { + _ = @as(u32, @splat(5)); +} + +// error +// backend=stage2 +// target=native +// +// :2:18: error: expected vector type, found 'u32' -- 2.54.0