Commit c5260f7f86

LemonBoy <thatlemon@gmail.com>
2020-02-13 00:38:59
ir: Allow implicit conversion between vector types
Only valid when the number of elements match and the types are compatible. Fixes #4334
1 parent 4578d13
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -14840,6 +14840,16 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
         }
     }
 
+    // @Vector(N,T1) to @Vector(N,T2)
+    if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector) {
+        if (actual_type->data.vector.len == wanted_type->data.vector.len &&
+            types_match_const_cast_only(ira, wanted_type->data.vector.elem_type,
+                actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
+        {
+            return ir_analyze_bit_cast(ira, source_instr, value, wanted_type);
+        }
+    }
+
     // *@Frame(func) to anyframe->T or anyframe
     // *@Frame(func) to ?anyframe->T or ?anyframe
     // *@Frame(func) to E!anyframe->T or E!anyframe
@@ -16409,9 +16419,11 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
         case ZigTypeIdComptimeInt:
         case ZigTypeIdInt:
         case ZigTypeIdFloat:
-        case ZigTypeIdVector:
             zig_unreachable(); // handled with the type_is_numeric checks above
 
+        case ZigTypeIdVector:
+            // Not every case is handled by the type_is_numeric checks above,
+            // vectors of bool trigger this code path
         case ZigTypeIdBool:
         case ZigTypeIdMetaType:
         case ZigTypeIdVoid:
test/stage1/behavior/vector.zig
@@ -1,6 +1,7 @@
 const std = @import("std");
 const mem = std.mem;
 const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
 const builtin = @import("builtin");
 
 test "implicit cast vector to array - bool" {
@@ -250,3 +251,29 @@ test "initialize vector which is a struct field" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "vector comparison operators" {
+    const S = struct {
+        fn doTheTest() void {
+            {
+                const v1: @Vector(4, bool) = [_]bool{ true, false, true, false };
+                const v2: @Vector(4, bool) = [_]bool{ false, true, false, true };
+                expectEqual(@splat(4, true), v1 == v1);
+                expectEqual(@splat(4, false), v1 == v2);
+                expectEqual(@splat(4, true), v1 != v2);
+                expectEqual(@splat(4, false), v2 != v2);
+            }
+            {
+                const v1 = @splat(4, @as(u32, 0xc0ffeeee));
+                const v2: @Vector(4, c_uint) = v1;
+                const v3 = @splat(4, @as(u32, 0xdeadbeef));
+                expectEqual(@splat(4, true), v1 == v2);
+                expectEqual(@splat(4, false), v1 == v3);
+                expectEqual(@splat(4, true), v1 != v3);
+                expectEqual(@splat(4, false), v1 != v2);
+            }
+        }
+    };
+    S.doTheTest();
+    comptime S.doTheTest();
+}