From 2485f3004659723a1ccd2799a6e0bddb09e32d3b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 14 Mar 2020 16:55:27 +0100 Subject: [PATCH] ir: Support bitwise not on vectors --- src/ir.cpp | 51 +++++++++++++++++++++++---------- test/stage1/behavior/vector.zig | 25 ++++++++++++++++ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 04eaa217b9..436db592f2 100644 --- a/src/ir.cpp +++ b/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; - } - - return ir_build_binary_not(ira, &instruction->base.base, value, expr_type); + 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; } - 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 result; + } + + return ir_build_binary_not(ira, &instruction->base.base, value, expr_type); } static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *instruction) { diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig index 6db695bfa3..f242aa0fbf 100644 --- a/test/stage1/behavior/vector.zig +++ b/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(); +}