Commit 2485f30046

LemonBoy <thatlemon@gmail.com>
2020-03-14 16:55:27
ir: Support bitwise not on vectors
1 parent 54ffcf9
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -20363,24 +20363,45 @@ static IrInstGen *ir_analyze_bin_not(IrAnalyze *ira, IrInstSrcUnOp *instruction)
     if (type_is_invalid(expr_type))
         return ira->codegen->invalid_inst_gen;
 
-    if (expr_type->id == ZigTypeIdInt) {
-        if (instr_is_comptime(value)) {
-            ZigValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
-            if (target_const_val == nullptr)
-                return ira->codegen->invalid_inst_gen;
+    ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ?
+        expr_type->data.vector.elem_type : expr_type;
 
-            IrInstGen *result = ir_const(ira, &instruction->base.base, expr_type);
-            bigint_not(&result->value->data.x_bigint, &target_const_val->data.x_bigint,
-                    expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
-            return result;
+    if (scalar_type->id != ZigTypeIdInt) {
+        ir_add_error(ira, &instruction->base.base,
+            buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
+        return ira->codegen->invalid_inst_gen;
+    }
+
+    if (instr_is_comptime(value)) {
+        ZigValue *expr_val = ir_resolve_const(ira, value, UndefBad);
+        if (expr_val == nullptr)
+            return ira->codegen->invalid_inst_gen;
+
+        IrInstGen *result = ir_const(ira, &instruction->base.base, expr_type);
+
+        if (expr_type->id == ZigTypeIdVector) {
+            expand_undef_array(ira->codegen, expr_val);
+            result->value->special = ConstValSpecialUndef;
+            expand_undef_array(ira->codegen, result->value);
+
+            for (size_t i = 0; i < expr_type->data.vector.len; i++) {
+                ZigValue *src_val = &expr_val->data.x_array.data.s_none.elements[i];
+                ZigValue *dst_val = &result->value->data.x_array.data.s_none.elements[i];
+
+                dst_val->type = scalar_type;
+                dst_val->special = ConstValSpecialStatic;
+                bigint_not(&dst_val->data.x_bigint, &src_val->data.x_bigint,
+                    scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
+            }
+        } else {
+            bigint_not(&result->value->data.x_bigint, &expr_val->data.x_bigint,
+                scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
         }
 
-        return ir_build_binary_not(ira, &instruction->base.base, value, expr_type);
+        return result;
     }
 
-    ir_add_error(ira, &instruction->base.base,
-            buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
-    return ira->codegen->invalid_inst_gen;
+    return ir_build_binary_not(ira, &instruction->base.base, value, expr_type);
 }
 
 static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *instruction) {
test/stage1/behavior/vector.zig
@@ -351,3 +351,28 @@ test "vector division operators" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "vector bitwise not operator" {
+    const S = struct {
+        fn doTheTestNot(comptime T: type, x: @Vector(4, T)) void {
+            var y = ~x;
+            for (@as([4]T, y)) |v, i| {
+                expectEqual(~x[i], v);
+            }
+        }
+        fn doTheTest() void {
+            doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
+            doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
+            doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
+            doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
+
+            doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
+            doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
+            doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
+            doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
+        }
+    };
+
+    S.doTheTest();
+    comptime S.doTheTest();
+}