| author | |
| committer | |
| log | 7140d08334de7d3c0c1342a0c2eb8a8db638b5df |
| tree | c031195d03ff3ce11e65a7342eab968a64767d3f |
| parent | f4c4daec863cf7394e141aefc5ad52e9c34f5979 |
- use logical ops for boolean bitwise instructions
- normalize strange-int results in airArithOp, airReduce, and airIntCast
Co-authored-by: Quint Daenen <quint@daenen.email>10 files changed, 62 insertions(+), 45 deletions(-)
src/codegen/spirv/CodeGen.zig+51-20| ... | @@ -3016,9 +3016,9 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -3016,9 +3016,9 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void { |
| 3016 | .ptr_add => try cg.airPtrAdd(inst), | 3016 | .ptr_add => try cg.airPtrAdd(inst), |
| 3017 | .ptr_sub => try cg.airPtrSub(inst), | 3017 | .ptr_sub => try cg.airPtrSub(inst), |
| 3018 | 3018 | ||
| 3019 | .bit_and => try cg.airBinOpSimple(inst, .OpBitwiseAnd), | 3019 | .bit_and => try cg.airBitwiseOp(inst, .bit_and), |
| 3020 | .bit_or => try cg.airBinOpSimple(inst, .OpBitwiseOr), | 3020 | .bit_or => try cg.airBitwiseOp(inst, .bit_or), |
| 3021 | .xor => try cg.airBinOpSimple(inst, .OpBitwiseXor), | 3021 | .xor => try cg.airBitwiseOp(inst, .xor), |
| 3022 | 3022 | ||
| 3023 | .shl, .shl_exact => try cg.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical), | 3023 | .shl, .shl_exact => try cg.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical), |
| 3024 | .shr, .shr_exact => try cg.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic), | 3024 | .shr, .shr_exact => try cg.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic), |
| ... | @@ -3145,6 +3145,34 @@ fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: Opcode) !?Id { | ... | @@ -3145,6 +3145,34 @@ fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: Opcode) !?Id { |
| 3145 | return try result.materialize(cg); | 3145 | return try result.materialize(cg); |
| 3146 | } | 3146 | } |
| 3147 | 3147 | ||
| 3148 | const BitwiseOp = enum { bit_and, bit_or, xor }; | ||
| 3149 | |||
| 3150 | fn airBitwiseOp(cg: *CodeGen, inst: Air.Inst.Index, op: BitwiseOp) !?Id { | ||
| 3151 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 3152 | const lhs = try cg.temporary(bin_op.lhs); | ||
| 3153 | const rhs = try cg.temporary(bin_op.rhs); | ||
| 3154 | const info = cg.arithmeticTypeInfo(lhs.ty); | ||
| 3155 | |||
| 3156 | // SPIR-V requires logical opcodes for booleans, bitwise opcodes for integers. | ||
| 3157 | const opcode: Opcode = switch (info.class) { | ||
| 3158 | .bool => switch (op) { | ||
| 3159 | .bit_and => .OpLogicalAnd, | ||
| 3160 | .bit_or => .OpLogicalOr, | ||
| 3161 | .xor => .OpLogicalNotEqual, | ||
| 3162 | }, | ||
| 3163 | .integer, .strange_integer => switch (op) { | ||
| 3164 | .bit_and => .OpBitwiseAnd, | ||
| 3165 | .bit_or => .OpBitwiseOr, | ||
| 3166 | .xor => .OpBitwiseXor, | ||
| 3167 | }, | ||
| 3168 | .float => unreachable, | ||
| 3169 | .composite_integer => unreachable, // TODO | ||
| 3170 | }; | ||
| 3171 | |||
| 3172 | const result = try cg.buildBinary(opcode, lhs, rhs); | ||
| 3173 | return try result.materialize(cg); | ||
| 3174 | } | ||
| 3175 | |||
| 3148 | fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode) !?Id { | 3176 | fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode) !?Id { |
| 3149 | const zcu = cg.module.zcu; | 3177 | const zcu = cg.module.zcu; |
| 3150 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3178 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | @@ -3389,9 +3417,12 @@ fn airArithOp( | ... | @@ -3389,9 +3417,12 @@ fn airArithOp( |
| 3389 | const info = cg.arithmeticTypeInfo(lhs.ty); | 3417 | const info = cg.arithmeticTypeInfo(lhs.ty); |
| 3390 | const result = switch (info.class) { | 3418 | const result = switch (info.class) { |
| 3391 | .composite_integer => unreachable, // TODO | 3419 | .composite_integer => unreachable, // TODO |
| 3392 | .integer, .strange_integer => switch (info.signedness) { | 3420 | .integer, .strange_integer => res: { |
| 3393 | .signed => try cg.buildBinary(sop, lhs, rhs), | 3421 | const raw = switch (info.signedness) { |
| 3394 | .unsigned => try cg.buildBinary(uop, lhs, rhs), | 3422 | .signed => try cg.buildBinary(sop, lhs, rhs), |
| 3423 | .unsigned => try cg.buildBinary(uop, lhs, rhs), | ||
| 3424 | }; | ||
| 3425 | break :res try cg.normalize(raw, info); | ||
| 3395 | }, | 3426 | }, |
| 3396 | .float => try cg.buildBinary(fop, lhs, rhs), | 3427 | .float => try cg.buildBinary(fop, lhs, rhs), |
| 3397 | .bool => unreachable, | 3428 | .bool => unreachable, |
| ... | @@ -3766,7 +3797,6 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3766,7 +3797,6 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3766 | const operand = try cg.resolve(reduce.operand); | 3797 | const operand = try cg.resolve(reduce.operand); |
| 3767 | const operand_ty = cg.typeOf(reduce.operand); | 3798 | const operand_ty = cg.typeOf(reduce.operand); |
| 3768 | const scalar_ty = operand_ty.scalarType(zcu); | 3799 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3769 | const scalar_ty_id = try cg.resolveType(scalar_ty, .direct); | ||
| 3770 | const info = cg.arithmeticTypeInfo(operand_ty); | 3800 | const info = cg.arithmeticTypeInfo(operand_ty); |
| 3771 | const len = operand_ty.vectorLen(zcu); | 3801 | const len = operand_ty.vectorLen(zcu); |
| 3772 | const first = try cg.extractVectorComponent(scalar_ty, operand, 0); | 3802 | const first = try cg.extractVectorComponent(scalar_ty, operand, 0); |
| ... | @@ -3792,8 +3822,6 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3792,8 +3822,6 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3792 | else => {}, | 3822 | else => {}, |
| 3793 | } | 3823 | } |
| 3794 | 3824 | ||
| 3795 | var result_id = first; | ||
| 3796 | |||
| 3797 | const opcode: Opcode = switch (info.class) { | 3825 | const opcode: Opcode = switch (info.class) { |
| 3798 | .bool => switch (reduce.operation) { | 3826 | .bool => switch (reduce.operation) { |
| 3799 | .And => .OpLogicalAnd, | 3827 | .And => .OpLogicalAnd, |
| ... | @@ -3817,19 +3845,18 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -3817,19 +3845,18 @@ fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 3817 | .composite_integer => unreachable, // TODO | 3845 | .composite_integer => unreachable, // TODO |
| 3818 | }; | 3846 | }; |
| 3819 | 3847 | ||
| 3820 | for (1..len) |i| { | 3848 | const needs_normalize = info.class == .strange_integer and |
| 3821 | const lhs = result_id; | 3849 | (reduce.operation == .Add or reduce.operation == .Mul); |
| 3822 | const rhs = try cg.extractVectorComponent(scalar_ty, operand, @intCast(i)); | ||
| 3823 | result_id = cg.module.allocId(); | ||
| 3824 | 3850 | ||
| 3825 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | 3851 | var result: Temporary = .init(scalar_ty, first); |
| 3826 | cg.body.writeOperand(Id, scalar_ty_id); | 3852 | for (1..len) |i| { |
| 3827 | cg.body.writeOperand(Id, result_id); | 3853 | const rhs_id = try cg.extractVectorComponent(scalar_ty, operand, @intCast(i)); |
| 3828 | cg.body.writeOperand(Id, lhs); | 3854 | const rhs: Temporary = .init(scalar_ty, rhs_id); |
| 3829 | cg.body.writeOperand(Id, rhs); | 3855 | const stepped = try cg.buildBinary(opcode, result, rhs); |
| 3856 | result = if (needs_normalize) try cg.normalize(stepped, info) else stepped; | ||
| 3830 | } | 3857 | } |
| 3831 | 3858 | ||
| 3832 | return result_id; | 3859 | return try result.materialize(cg); |
| 3833 | } | 3860 | } |
| 3834 | 3861 | ||
| 3835 | fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 3862 | fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| ... | @@ -4314,7 +4341,11 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4314,7 +4341,11 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4314 | const dst_info = cg.arithmeticTypeInfo(dst_ty); | 4341 | const dst_info = cg.arithmeticTypeInfo(dst_ty); |
| 4315 | 4342 | ||
| 4316 | if (src_info.backing_bits == dst_info.backing_bits) { | 4343 | if (src_info.backing_bits == dst_info.backing_bits) { |
| 4317 | return try src.materialize(cg); | 4344 | const result = if (dst_info.bits < src_info.bits) |
| 4345 | try cg.normalize(src.pun(dst_ty), dst_info) | ||
| 4346 | else | ||
| 4347 | src.pun(dst_ty); | ||
| 4348 | return try result.materialize(cg); | ||
| 4318 | } | 4349 | } |
| 4319 | 4350 | ||
| 4320 | const converted = try cg.buildConvert(dst_ty, src); | 4351 | const converted = try cg.buildConvert(dst_ty, src); |
test/behavior/bool.zig-1| ... | @@ -10,7 +10,6 @@ test "bool literals" { | ... | @@ -10,7 +10,6 @@ test "bool literals" { |
| 10 | 10 | ||
| 11 | test "cast bool to int" { | 11 | test "cast bool to int" { |
| 12 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 12 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 13 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 14 | 13 | ||
| 15 | const t = true; | 14 | const t = true; |
| 16 | const f = false; | 15 | const f = false; |
test/behavior/cast_int.zig-2| ... | @@ -19,7 +19,6 @@ test "@intCast i32 to u7" { | ... | @@ -19,7 +19,6 @@ test "@intCast i32 to u7" { |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | test "coerce i8 to i32 and @intCast back" { | 21 | test "coerce i8 to i32 and @intCast back" { |
| 22 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 23 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 22 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 23 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 25 | 24 | ||
| ... | @@ -35,7 +34,6 @@ test "coerce i8 to i32 and @intCast back" { | ... | @@ -35,7 +34,6 @@ test "coerce i8 to i32 and @intCast back" { |
| 35 | } | 34 | } |
| 36 | 35 | ||
| 37 | test "coerce non byte-sized integers accross 32bits boundary" { | 36 | test "coerce non byte-sized integers accross 32bits boundary" { |
| 38 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 39 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 37 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 40 | 38 | ||
| 41 | { | 39 | { |
test/behavior/duplicated_test_names.zig-1| ... | @@ -15,7 +15,6 @@ comptime { | ... | @@ -15,7 +15,6 @@ comptime { |
| 15 | test "thingy" {} | 15 | test "thingy" {} |
| 16 | 16 | ||
| 17 | test thingy { | 17 | test thingy { |
| 18 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 19 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 18 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 20 | 19 | ||
| 21 | if (thingy(1, 2) != 3) unreachable; | 20 | if (thingy(1, 2) != 3) unreachable; |
test/behavior/hasdecl.zig-2| ... | @@ -13,7 +13,6 @@ const Bar = struct { | ... | @@ -13,7 +13,6 @@ const Bar = struct { |
| 13 | 13 | ||
| 14 | test "@hasDecl" { | 14 | test "@hasDecl" { |
| 15 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 15 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 16 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 17 | 16 | ||
| 18 | try expect(@hasDecl(Foo, "public_thing")); | 17 | try expect(@hasDecl(Foo, "public_thing")); |
| 19 | try expect(!@hasDecl(Foo, "private_thing")); | 18 | try expect(!@hasDecl(Foo, "private_thing")); |
| ... | @@ -26,7 +25,6 @@ test "@hasDecl" { | ... | @@ -26,7 +25,6 @@ test "@hasDecl" { |
| 26 | 25 | ||
| 27 | test "@hasDecl using a sliced string literal" { | 26 | test "@hasDecl using a sliced string literal" { |
| 28 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 27 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 29 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 30 | 28 | ||
| 31 | try expect(@hasDecl(@This(), "std") == true); | 29 | try expect(@hasDecl(@This(), "std") == true); |
| 32 | try expect(@hasDecl(@This(), "std"[0..0]) == false); | 30 | try expect(@hasDecl(@This(), "std"[0..0]) == false); |
test/behavior/import.zig-3| ... | @@ -5,21 +5,18 @@ const expectEqual = std.testing.expectEqual; | ... | @@ -5,21 +5,18 @@ const expectEqual = std.testing.expectEqual; |
| 5 | const a_namespace = @import("import/a_namespace.zig"); | 5 | const a_namespace = @import("import/a_namespace.zig"); |
| 6 | 6 | ||
| 7 | test "call fn via namespace lookup" { | 7 | test "call fn via namespace lookup" { |
| 8 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 8 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 10 | 9 | ||
| 11 | try expect(@as(i32, 1234) == a_namespace.foo()); | 10 | try expect(@as(i32, 1234) == a_namespace.foo()); |
| 12 | } | 11 | } |
| 13 | 12 | ||
| 14 | test "importing the same thing gives the same import" { | 13 | test "importing the same thing gives the same import" { |
| 15 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 16 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 14 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 17 | 15 | ||
| 18 | try expect(@import("std") == @import("std")); | 16 | try expect(@import("std") == @import("std")); |
| 19 | } | 17 | } |
| 20 | 18 | ||
| 21 | test "import empty file" { | 19 | test "import empty file" { |
| 22 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 23 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 24 | 21 | ||
| 25 | _ = @import("import/empty.zig"); | 22 | _ = @import("import/empty.zig"); |
test/behavior/ir_block_deps.zig+1-1| ... | @@ -19,8 +19,8 @@ fn getErrInt() anyerror!i32 { | ... | @@ -19,8 +19,8 @@ fn getErrInt() anyerror!i32 { |
| 19 | 19 | ||
| 20 | test "ir block deps" { | 20 | test "ir block deps" { |
| 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 22 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 23 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 22 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 23 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 24 | 24 | ||
| 25 | try expect((foo(1) catch unreachable) == 0); | 25 | try expect((foo(1) catch unreachable) == 0); |
| 26 | try expect((foo(2) catch unreachable) == 0); | 26 | try expect((foo(2) catch unreachable) == 0); |
test/behavior/namespace_depends_on_compile_var.zig-1| ... | @@ -3,7 +3,6 @@ const builtin = @import("builtin"); | ... | @@ -3,7 +3,6 @@ const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | test "namespace depends on compile var" { | 5 | test "namespace depends on compile var" { |
| 6 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 7 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 6 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 8 | 7 | ||
| 9 | if (some_namespace.a_bool) { | 8 | if (some_namespace.a_bool) { |
test/behavior/pub_enum.zig-2| ... | @@ -3,7 +3,6 @@ const other = @import("pub_enum/other.zig"); | ... | @@ -3,7 +3,6 @@ const other = @import("pub_enum/other.zig"); |
| 3 | const expect = @import("std").testing.expect; | 3 | const expect = @import("std").testing.expect; |
| 4 | 4 | ||
| 5 | test "pub enum" { | 5 | test "pub enum" { |
| 6 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 7 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 6 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 8 | 7 | ||
| 9 | try pubEnumTest(other.APubEnum.Two); | 8 | try pubEnumTest(other.APubEnum.Two); |
| ... | @@ -13,7 +12,6 @@ fn pubEnumTest(foo: other.APubEnum) !void { | ... | @@ -13,7 +12,6 @@ fn pubEnumTest(foo: other.APubEnum) !void { |
| 13 | } | 12 | } |
| 14 | 13 | ||
| 15 | test "cast with imported symbol" { | 14 | test "cast with imported symbol" { |
| 16 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 17 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 15 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 18 | 16 | ||
| 19 | try expect(@as(other.size_t, 42) == 42); | 17 | try expect(@as(other.size_t, 42) == 42); |
test/behavior/wrapping_arithmetic.zig+10-12| ... | @@ -3,9 +3,9 @@ const builtin = @import("builtin"); | ... | @@ -3,9 +3,9 @@ const builtin = @import("builtin"); |
| 3 | const minInt = std.math.minInt; | 3 | const minInt = std.math.minInt; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | const expect = std.testing.expect; | 5 | const expect = std.testing.expect; |
| 6 | const skip128 = builtin.zig_backend == .stage2_spirv; | ||
| 6 | 7 | ||
| 7 | test "wrapping add" { | 8 | test "wrapping add" { |
| 8 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 10 | 10 | ||
| 11 | const S = struct { | 11 | const S = struct { |
| ... | @@ -14,14 +14,14 @@ test "wrapping add" { | ... | @@ -14,14 +14,14 @@ test "wrapping add" { |
| 14 | try testWrapAdd(i8, -128, -128, 0); | 14 | try testWrapAdd(i8, -128, -128, 0); |
| 15 | try testWrapAdd(i2, 1, 1, -2); | 15 | try testWrapAdd(i2, 1, 1, -2); |
| 16 | try testWrapAdd(i64, maxInt(i64), 1, minInt(i64)); | 16 | try testWrapAdd(i64, maxInt(i64), 1, minInt(i64)); |
| 17 | try testWrapAdd(i128, maxInt(i128), -maxInt(i128), 0); | 17 | if (!skip128) try testWrapAdd(i128, maxInt(i128), -maxInt(i128), 0); |
| 18 | try testWrapAdd(i128, minInt(i128), maxInt(i128), -1); | 18 | if (!skip128) try testWrapAdd(i128, minInt(i128), maxInt(i128), -1); |
| 19 | try testWrapAdd(i8, 127, 127, -2); | 19 | try testWrapAdd(i8, 127, 127, -2); |
| 20 | try testWrapAdd(u8, 3, 10, 13); | 20 | try testWrapAdd(u8, 3, 10, 13); |
| 21 | try testWrapAdd(u8, 255, 255, 254); | 21 | try testWrapAdd(u8, 255, 255, 254); |
| 22 | try testWrapAdd(u2, 3, 2, 1); | 22 | try testWrapAdd(u2, 3, 2, 1); |
| 23 | try testWrapAdd(u3, 7, 1, 0); | 23 | try testWrapAdd(u3, 7, 1, 0); |
| 24 | try testWrapAdd(u128, maxInt(u128), 1, minInt(u128)); | 24 | if (!skip128) try testWrapAdd(u128, maxInt(u128), 1, minInt(u128)); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | fn testWrapAdd(comptime T: type, lhs: T, rhs: T, expected: T) !void { | 27 | fn testWrapAdd(comptime T: type, lhs: T, rhs: T, expected: T) !void { |
| ... | @@ -43,7 +43,6 @@ test "wrapping add" { | ... | @@ -43,7 +43,6 @@ test "wrapping add" { |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | test "wrapping subtraction" { | 45 | test "wrapping subtraction" { |
| 46 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 47 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 46 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 48 | 47 | ||
| 49 | const S = struct { | 48 | const S = struct { |
| ... | @@ -52,12 +51,12 @@ test "wrapping subtraction" { | ... | @@ -52,12 +51,12 @@ test "wrapping subtraction" { |
| 52 | try testWrapSub(i8, -128, -128, 0); | 51 | try testWrapSub(i8, -128, -128, 0); |
| 53 | try testWrapSub(i8, -1, 127, -128); | 52 | try testWrapSub(i8, -1, 127, -128); |
| 54 | try testWrapSub(i64, minInt(i64), 1, maxInt(i64)); | 53 | try testWrapSub(i64, minInt(i64), 1, maxInt(i64)); |
| 55 | try testWrapSub(i128, maxInt(i128), -1, minInt(i128)); | 54 | if (!skip128) try testWrapSub(i128, maxInt(i128), -1, minInt(i128)); |
| 56 | try testWrapSub(i128, minInt(i128), -maxInt(i128), -1); | 55 | if (!skip128) try testWrapSub(i128, minInt(i128), -maxInt(i128), -1); |
| 57 | try testWrapSub(u8, 10, 3, 7); | 56 | try testWrapSub(u8, 10, 3, 7); |
| 58 | try testWrapSub(u8, 0, 255, 1); | 57 | try testWrapSub(u8, 0, 255, 1); |
| 59 | try testWrapSub(u5, 0, 31, 1); | 58 | try testWrapSub(u5, 0, 31, 1); |
| 60 | try testWrapSub(u128, 0, maxInt(u128), 1); | 59 | if (!skip128) try testWrapSub(u128, 0, maxInt(u128), 1); |
| 61 | } | 60 | } |
| 62 | 61 | ||
| 63 | fn testWrapSub(comptime T: type, lhs: T, rhs: T, expected: T) !void { | 62 | fn testWrapSub(comptime T: type, lhs: T, rhs: T, expected: T) !void { |
| ... | @@ -79,7 +78,6 @@ test "wrapping subtraction" { | ... | @@ -79,7 +78,6 @@ test "wrapping subtraction" { |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | test "wrapping multiplication" { | 80 | test "wrapping multiplication" { |
| 82 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | ||
| 83 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | 81 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 84 | 82 | ||
| 85 | const S = struct { | 83 | const S = struct { |
| ... | @@ -90,11 +88,11 @@ test "wrapping multiplication" { | ... | @@ -90,11 +88,11 @@ test "wrapping multiplication" { |
| 90 | try testWrapMul(i8, -128, -128, 0); | 88 | try testWrapMul(i8, -128, -128, 0); |
| 91 | try testWrapMul(i8, maxInt(i8), maxInt(i8), 1); | 89 | try testWrapMul(i8, maxInt(i8), maxInt(i8), 1); |
| 92 | try testWrapMul(i16, maxInt(i16), -1, minInt(i16) + 1); | 90 | try testWrapMul(i16, maxInt(i16), -1, minInt(i16) + 1); |
| 93 | try testWrapMul(i128, maxInt(i128), -1, minInt(i128) + 1); | 91 | if (!skip128) try testWrapMul(i128, maxInt(i128), -1, minInt(i128) + 1); |
| 94 | try testWrapMul(i128, minInt(i128), -1, minInt(i128)); | 92 | if (!skip128) try testWrapMul(i128, minInt(i128), -1, minInt(i128)); |
| 95 | try testWrapMul(u8, 10, 3, 30); | 93 | try testWrapMul(u8, 10, 3, 30); |
| 96 | try testWrapMul(u8, 2, 255, 254); | 94 | try testWrapMul(u8, 2, 255, 254); |
| 97 | try testWrapMul(u128, maxInt(u128), maxInt(u128), 1); | 95 | if (!skip128) try testWrapMul(u128, maxInt(u128), maxInt(u128), 1); |
| 98 | } | 96 | } |
| 99 | 97 | ||
| 100 | fn testWrapMul(comptime T: type, lhs: T, rhs: T, expected: T) !void { | 98 | fn testWrapMul(comptime T: type, lhs: T, rhs: T, expected: T) !void { |