authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-28 14:17:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-28 14:17:05-07:00
logb6ccde47adeb0dbd7b39150c36498100e0d98075
treec9fff157c08701cd6d6849a1c95fddd5385e1c86
parent691c7cb3cd3cc6cb4f6324d0ad4a5c3e2e8ff94c

Sema: allow mixing array and vector operands

* Added peer type resolution for arrays and vectors: the vector type is selected. * Fixed passing the lhs type or rhs type instead of the peer resolved type when calling Value methods during analyzeArithmetic handling of comptime expressions. * `checkVectorizableBinaryOperands` now allows mixing vectors and arrays, as long as one of the operands is a vector. This matches stage1's handling of `^=` but apparently stage1 is inconsistent and does not handle e.g. `*=`. stage2 now will always allow mixing vector and array operands for all operations.

2 files changed, 61 insertions(+), 14 deletions(-)

src/Sema.zig+37-14
......@@ -9617,7 +9617,7 @@ fn analyzeArithmetic(
96179617 if (lhs_val.isUndef()) {
96189618 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
96199619 if (maybe_rhs_val) |rhs_val| {
9620 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty, target)) {
9620 if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) {
96219621 return sema.addConstUndef(resolved_type);
96229622 }
96239623 }
......@@ -9692,7 +9692,7 @@ fn analyzeArithmetic(
96929692 if (lhs_val.isUndef()) {
96939693 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
96949694 if (maybe_rhs_val) |rhs_val| {
9695 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty, target)) {
9695 if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) {
96969696 return sema.addConstUndef(resolved_type);
96979697 }
96989698 }
......@@ -9755,7 +9755,7 @@ fn analyzeArithmetic(
97559755 if (lhs_val.isUndef()) {
97569756 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
97579757 if (maybe_rhs_val) |rhs_val| {
9758 if (rhs_val.compare(.neq, Value.negative_one, rhs_ty, target)) {
9758 if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) {
97599759 return sema.addConstUndef(resolved_type);
97609760 }
97619761 }
......@@ -9845,7 +9845,7 @@ fn analyzeArithmetic(
98459845 if (lhs_val.compareWithZero(.eq)) {
98469846 return sema.addConstant(resolved_type, Value.zero);
98479847 }
9848 if (lhs_val.compare(.eq, Value.one, lhs_ty, target)) {
9848 if (lhs_val.compare(.eq, Value.one, resolved_type, target)) {
98499849 return casted_rhs;
98509850 }
98519851 }
......@@ -9861,7 +9861,7 @@ fn analyzeArithmetic(
98619861 if (rhs_val.compareWithZero(.eq)) {
98629862 return sema.addConstant(resolved_type, Value.zero);
98639863 }
9864 if (rhs_val.compare(.eq, Value.one, rhs_ty, target)) {
9864 if (rhs_val.compare(.eq, Value.one, resolved_type, target)) {
98659865 return casted_lhs;
98669866 }
98679867 if (maybe_lhs_val) |lhs_val| {
......@@ -9896,7 +9896,7 @@ fn analyzeArithmetic(
98969896 if (lhs_val.compareWithZero(.eq)) {
98979897 return sema.addConstant(resolved_type, Value.zero);
98989898 }
9899 if (lhs_val.compare(.eq, Value.one, lhs_ty, target)) {
9899 if (lhs_val.compare(.eq, Value.one, resolved_type, target)) {
99009900 return casted_rhs;
99019901 }
99029902 }
......@@ -9908,7 +9908,7 @@ fn analyzeArithmetic(
99089908 if (rhs_val.compareWithZero(.eq)) {
99099909 return sema.addConstant(resolved_type, Value.zero);
99109910 }
9911 if (rhs_val.compare(.eq, Value.one, rhs_ty, target)) {
9911 if (rhs_val.compare(.eq, Value.one, resolved_type, target)) {
99129912 return casted_lhs;
99139913 }
99149914 if (maybe_lhs_val) |lhs_val| {
......@@ -9932,7 +9932,7 @@ fn analyzeArithmetic(
99329932 if (lhs_val.compareWithZero(.eq)) {
99339933 return sema.addConstant(resolved_type, Value.zero);
99349934 }
9935 if (lhs_val.compare(.eq, Value.one, lhs_ty, target)) {
9935 if (lhs_val.compare(.eq, Value.one, resolved_type, target)) {
99369936 return casted_rhs;
99379937 }
99389938 }
......@@ -9944,7 +9944,7 @@ fn analyzeArithmetic(
99449944 if (rhs_val.compareWithZero(.eq)) {
99459945 return sema.addConstant(resolved_type, Value.zero);
99469946 }
9947 if (rhs_val.compare(.eq, Value.one, rhs_ty, target)) {
9947 if (rhs_val.compare(.eq, Value.one, resolved_type, target)) {
99489948 return casted_lhs;
99499949 }
99509950 if (maybe_lhs_val) |lhs_val| {
......@@ -14521,9 +14521,20 @@ fn checkVectorizableBinaryOperands(
1452114521) CompileError!void {
1452214522 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
1452314523 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
14524 if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) {
14525 const lhs_len = lhs_ty.vectorLen();
14526 const rhs_len = rhs_ty.vectorLen();
14524 if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return;
14525
14526 const lhs_is_vector = switch (lhs_zig_ty_tag) {
14527 .Vector, .Array => true,
14528 else => false,
14529 };
14530 const rhs_is_vector = switch (rhs_zig_ty_tag) {
14531 .Vector, .Array => true,
14532 else => false,
14533 };
14534
14535 if (lhs_is_vector and rhs_is_vector) {
14536 const lhs_len = lhs_ty.arrayLen();
14537 const rhs_len = rhs_ty.arrayLen();
1452714538 if (lhs_len != rhs_len) {
1452814539 const msg = msg: {
1452914540 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});
......@@ -14534,14 +14545,14 @@ fn checkVectorizableBinaryOperands(
1453414545 };
1453514546 return sema.failWithOwnedErrorMsg(block, msg);
1453614547 }
14537 } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) {
14548 } else {
1453814549 const target = sema.mod.getTarget();
1453914550 const msg = msg: {
1454014551 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{
1454114552 lhs_ty.fmt(target), rhs_ty.fmt(target),
1454214553 });
1454314554 errdefer msg.destroy(sema.gpa);
14544 if (lhs_zig_ty_tag == .Vector) {
14555 if (lhs_is_vector) {
1454514556 try sema.errNote(block, lhs_src, msg, "vector here", .{});
1454614557 try sema.errNote(block, rhs_src, msg, "scalar here", .{});
1454714558 } else {
......@@ -21017,6 +21028,18 @@ fn resolvePeerTypes(
2101721028 chosen_i = candidate_i + 1;
2101821029 continue;
2101921030 },
21031 .Vector => switch (chosen_ty_tag) {
21032 .Array => {
21033 chosen = candidate;
21034 chosen_i = candidate_i + 1;
21035 continue;
21036 },
21037 else => {},
21038 },
21039 .Array => switch (chosen_ty_tag) {
21040 .Vector => continue,
21041 else => {},
21042 },
2102021043 else => {},
2102121044 }
2102221045
test/behavior/vector.zig+24
......@@ -879,3 +879,27 @@ test "saturating shift-left" {
879879 try S.doTheTest();
880880 comptime try S.doTheTest();
881881}
882
883test "multiplication-assignment operator with an array operand" {
884 if (builtin.zig_backend == .stage1) {
885 // stage1 emits a compile error
886 return error.SkipZigTest;
887 }
888 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
889 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
890 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
891 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
893
894 const S = struct {
895 fn doTheTest() !void {
896 var x: @Vector(3, i32) = .{ 1, 2, 3 };
897 x *= [_]i32{ 4, 5, 6 };
898 try expect(x[0] == 4);
899 try expect(x[1] == 10);
900 try expect(x[2] == 18);
901 }
902 };
903 try S.doTheTest();
904 comptime try S.doTheTest();
905}