| author | |
| committer | |
| log | 436f53f55d3191bfa56418d98130d763fa5a6b22 |
| tree | f9434f4e9bd566660997405d085a61ab505fc94b |
| parent | 97850149386a8ec54ffce285973d3e7010cefa00 |
6 files changed, 63 insertions(+), 12 deletions(-)
src/codegen/spirv.zig+59-2| ... | ... | @@ -2315,6 +2315,7 @@ const DeclGen = struct { |
| 2315 | 2315 | .sub, .sub_wrap, .sub_optimized => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| 2316 | 2316 | .mul, .mul_wrap, .mul_optimized => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul), |
| 2317 | 2317 | |
| 2318 | ||
| 2318 | 2319 | .abs => try self.airAbs(inst), |
| 2319 | 2320 | .floor => try self.airFloor(inst), |
| 2320 | 2321 | |
| ... | ... | @@ -2330,6 +2331,7 @@ const DeclGen = struct { |
| 2330 | 2331 | |
| 2331 | 2332 | .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan), |
| 2332 | 2333 | .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan), |
| 2334 | .mul_with_overflow => try self.airMulOverflow(inst), | |
| 2333 | 2335 | .shl_with_overflow => try self.airShlOverflow(inst), |
| 2334 | 2336 | |
| 2335 | 2337 | .mul_add => try self.airMulAdd(inst), |
| ... | ... | @@ -2733,8 +2735,8 @@ const DeclGen = struct { |
| 2733 | 2735 | else => unreachable, |
| 2734 | 2736 | }; |
| 2735 | 2737 | const set_id = switch (target.os.tag) { |
| 2736 | .opencl => try self.spv.importInstructionSet("OpenCL.std"), | |
| 2737 | .vulkan => try self.spv.importInstructionSet("GLSL.std.450"), | |
| 2738 | .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"), | |
| 2739 | .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"), | |
| 2738 | 2740 | else => unreachable, |
| 2739 | 2741 | }; |
| 2740 | 2742 | |
| ... | ... | @@ -2998,6 +3000,61 @@ const DeclGen = struct { |
| 2998 | 3000 | ); |
| 2999 | 3001 | } |
| 3000 | 3002 | |
| 3003 | fn airMulOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | |
| 3004 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 3005 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | |
| 3006 | const lhs = try self.resolve(extra.lhs); | |
| 3007 | const rhs = try self.resolve(extra.rhs); | |
| 3008 | ||
| 3009 | const result_ty = self.typeOfIndex(inst); | |
| 3010 | const operand_ty = self.typeOf(extra.lhs); | |
| 3011 | const ov_ty = result_ty.structFieldType(1, self.module); | |
| 3012 | ||
| 3013 | const info = self.arithmeticTypeInfo(operand_ty); | |
| 3014 | switch (info.class) { | |
| 3015 | .composite_integer => return self.todo("overflow ops for composite integers", .{}), | |
| 3016 | .strange_integer, .integer => {}, | |
| 3017 | .float, .bool => unreachable, | |
| 3018 | } | |
| 3019 | ||
| 3020 | var wip_result = try self.elementWise(operand_ty, true); | |
| 3021 | defer wip_result.deinit(); | |
| 3022 | var wip_ov = try self.elementWise(ov_ty, true); | |
| 3023 | defer wip_ov.deinit(); | |
| 3024 | ||
| 3025 | const zero_id = try self.constInt(wip_result.ty_ref, 0); | |
| 3026 | const zero_ov_id = try self.constInt(wip_ov.ty_ref, 0); | |
| 3027 | const one_ov_id = try self.constInt(wip_ov.ty_ref, 1); | |
| 3028 | ||
| 3029 | for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| { | |
| 3030 | const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i); | |
| 3031 | const rhs_elem_id = try wip_result.elementAt(operand_ty, rhs, i); | |
| 3032 | ||
| 3033 | result_id.* = try self.arithOp(wip_result.ty, lhs_elem_id, rhs_elem_id, .OpFMul, .OpIMul, .OpIMul); | |
| 3034 | ||
| 3035 | // (a != 0) and (x / a != b) | |
| 3036 | const not_zero_id = try self.cmp(.neq, Type.bool, wip_result.ty, lhs_elem_id, zero_id); | |
| 3037 | const res_rhs_id = try self.arithOp(wip_result.ty, result_id.*, lhs_elem_id, .OpFDiv, .OpSDiv, .OpUDiv); | |
| 3038 | const res_rhs_not_rhs_id = try self.cmp(.neq, Type.bool, wip_result.ty, res_rhs_id, rhs_elem_id); | |
| 3039 | const cond_id = try self.binOpSimple(Type.bool, not_zero_id, res_rhs_not_rhs_id, .OpLogicalAnd); | |
| 3040 | ||
| 3041 | ov_id.* = self.spv.allocId(); | |
| 3042 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | |
| 3043 | .id_result_type = wip_ov.ty_id, | |
| 3044 | .id_result = ov_id.*, | |
| 3045 | .condition = cond_id, | |
| 3046 | .object_1 = one_ov_id, | |
| 3047 | .object_2 = zero_ov_id, | |
| 3048 | }); | |
| 3049 | } | |
| 3050 | ||
| 3051 | return try self.constructStruct( | |
| 3052 | result_ty, | |
| 3053 | &.{ operand_ty, ov_ty }, | |
| 3054 | &.{ try wip_result.finalize(), try wip_ov.finalize() }, | |
| 3055 | ); | |
| 3056 | } | |
| 3057 | ||
| 3001 | 3058 | fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3002 | 3059 | const mod = self.module; |
| 3003 | 3060 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
src/codegen/spirv/Assembler.zig+4-1| ... | ... | @@ -263,7 +263,10 @@ fn processInstruction(self: *Assembler) !void { |
| 263 | 263 | .OpExtInstImport => blk: { |
| 264 | 264 | const set_name_offset = self.inst.operands.items[1].string; |
| 265 | 265 | const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0); |
| 266 | break :blk .{ .value = try self.spv.importInstructionSet(set_name) }; | |
| 266 | const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse { | |
| 267 | return self.fail(set_name_offset, "unknown instruction set: {s}", .{set_name}); | |
| 268 | }; | |
| 269 | break :blk .{ .value = try self.spv.importInstructionSet(set_tag) }; | |
| 267 | 270 | }, |
| 268 | 271 | else => switch (self.inst.opcode.class()) { |
| 269 | 272 | .TypeDeclaration => try self.processTypeInstruction(), |
test/behavior/for.zig-1| ... | ... | @@ -226,7 +226,6 @@ test "else continue outer for" { |
| 226 | 226 | |
| 227 | 227 | test "for loop with else branch" { |
| 228 | 228 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 229 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 230 | 229 | |
| 231 | 230 | { |
| 232 | 231 | var x = [_]u32{ 1, 2 }; |
test/behavior/hasdecl.zig-4| ... | ... | @@ -12,8 +12,6 @@ const Bar = struct { |
| 12 | 12 | }; |
| 13 | 13 | |
| 14 | 14 | test "@hasDecl" { |
| 15 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 16 | ||
| 17 | 15 | try expect(@hasDecl(Foo, "public_thing")); |
| 18 | 16 | try expect(!@hasDecl(Foo, "private_thing")); |
| 19 | 17 | try expect(!@hasDecl(Foo, "no_thing")); |
| ... | ... | @@ -24,8 +22,6 @@ test "@hasDecl" { |
| 24 | 22 | } |
| 25 | 23 | |
| 26 | 24 | test "@hasDecl using a sliced string literal" { |
| 27 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 28 | ||
| 29 | 25 | try expect(@hasDecl(@This(), "std") == true); |
| 30 | 26 | try expect(@hasDecl(@This(), "std"[0..0]) == false); |
| 31 | 27 | try expect(@hasDecl(@This(), "std"[0..1]) == false); |
test/behavior/math.zig-3| ... | ... | @@ -788,7 +788,6 @@ test "small int addition" { |
| 788 | 788 | test "basic @mulWithOverflow" { |
| 789 | 789 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 790 | 790 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 791 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 792 | 791 | |
| 793 | 792 | { |
| 794 | 793 | var a: u8 = 86; |
| ... | ... | @@ -821,7 +820,6 @@ test "basic @mulWithOverflow" { |
| 821 | 820 | test "extensive @mulWithOverflow" { |
| 822 | 821 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 823 | 822 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 824 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 825 | 823 | |
| 826 | 824 | { |
| 827 | 825 | var a: u5 = 3; |
| ... | ... | @@ -998,7 +996,6 @@ test "@mulWithOverflow bitsize > 32" { |
| 998 | 996 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 999 | 997 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1000 | 998 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1001 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1002 | 999 | |
| 1003 | 1000 | { |
| 1004 | 1001 | var a: u62 = 3; |
test/behavior/vector.zig-1| ... | ... | @@ -1136,7 +1136,6 @@ test "@mulWithOverflow" { |
| 1136 | 1136 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1137 | 1137 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1138 | 1138 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1139 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1140 | 1139 | |
| 1141 | 1140 | const S = struct { |
| 1142 | 1141 | fn doTheTest() !void { |