authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-04-06 13:37:25+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-04-06 13:37:25+02:00
log39420838061a9049fbc889212836a9d4d2ab9af4
treede835335172000e497871f9593bac17bcff882c0
parent3eeb70540d7f40526b4f4549deb6e2bc792bb3b2
parent436f53f55d3191bfa56418d98130d763fa5a6b22
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18984 from alichraghi/vector

spirv: implement `@divFloor`, `@floor`, `@mod` and `@mulWithOverflow`

11 files changed, 241 insertions(+), 75 deletions(-)

src/codegen/spirv.zig+198-38
...@@ -1016,7 +1016,7 @@ const DeclGen = struct {...@@ -1016,7 +1016,7 @@ const DeclGen = struct {
1016 const elem_ty = Type.fromInterned(array_type.child);1016 const elem_ty = Type.fromInterned(array_type.child);
1017 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);1017 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
10181018
1019 const constituents = try self.gpa.alloc(IdRef, @as(u32, @intCast(ty.arrayLenIncludingSentinel(mod))));1019 const constituents = try self.gpa.alloc(IdRef, @intCast(ty.arrayLenIncludingSentinel(mod)));
1020 defer self.gpa.free(constituents);1020 defer self.gpa.free(constituents);
10211021
1022 switch (aggregate.storage) {1022 switch (aggregate.storage) {
...@@ -1736,7 +1736,6 @@ const DeclGen = struct {...@@ -1736,7 +1736,6 @@ const DeclGen = struct {
1736 .EnumLiteral,1736 .EnumLiteral,
1737 .ComptimeFloat,1737 .ComptimeFloat,
1738 .ComptimeInt,1738 .ComptimeInt,
1739 .Type,
1740 => unreachable, // Must be comptime.1739 => unreachable, // Must be comptime.
17411740
1742 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),1741 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),
...@@ -2316,21 +2315,23 @@ const DeclGen = struct {...@@ -2316,21 +2315,23 @@ const DeclGen = struct {
2316 .sub, .sub_wrap, .sub_optimized => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub),2315 .sub, .sub_wrap, .sub_optimized => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub),
2317 .mul, .mul_wrap, .mul_optimized => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul),2316 .mul, .mul_wrap, .mul_optimized => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul),
23182317
2318
2319 .abs => try self.airAbs(inst),2319 .abs => try self.airAbs(inst),
2320 .floor => try self.airFloor(inst),
2321
2322 .div_floor => try self.airDivFloor(inst),
23202323
2321 .div_float,2324 .div_float,
2322 .div_float_optimized,2325 .div_float_optimized,
2323 // TODO: Check that this is the right operation.
2324 .div_trunc,2326 .div_trunc,
2325 .div_trunc_optimized,2327 .div_trunc_optimized => try self.airArithOp(inst, .OpFDiv, .OpSDiv, .OpUDiv),
2326 => try self.airArithOp(inst, .OpFDiv, .OpSDiv, .OpUDiv),2328 .rem, .rem_optimized => try self.airArithOp(inst, .OpFRem, .OpSRem, .OpSRem),
2327 // TODO: Check if this is the right operation2329 .mod, .mod_optimized => try self.airArithOp(inst, .OpFMod, .OpSMod, .OpSMod),
2328 .rem,2330
2329 .rem_optimized,
2330 => try self.airArithOp(inst, .OpFRem, .OpSRem, .OpSRem),
23312331
2332 .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan),2332 .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan),
2333 .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),2333 .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),
2334 .mul_with_overflow => try self.airMulOverflow(inst),
2334 .shl_with_overflow => try self.airShlOverflow(inst),2335 .shl_with_overflow => try self.airShlOverflow(inst),
23352336
2336 .mul_add => try self.airMulAdd(inst),2337 .mul_add => try self.airMulAdd(inst),
...@@ -2340,7 +2341,7 @@ const DeclGen = struct {...@@ -2340,7 +2341,7 @@ const DeclGen = struct {
23402341
2341 .splat => try self.airSplat(inst),2342 .splat => try self.airSplat(inst),
2342 .reduce, .reduce_optimized => try self.airReduce(inst),2343 .reduce, .reduce_optimized => try self.airReduce(inst),
2343 .shuffle => try self.airShuffle(inst),2344 .shuffle => try self.airShuffle(inst),
23442345
2345 .ptr_add => try self.airPtrAdd(inst),2346 .ptr_add => try self.airPtrAdd(inst),
2346 .ptr_sub => try self.airPtrSub(inst),2347 .ptr_sub => try self.airPtrSub(inst),
...@@ -2661,6 +2662,95 @@ const DeclGen = struct {...@@ -2661,6 +2662,95 @@ const DeclGen = struct {
2661 }2662 }
2662 }2663 }
26632664
2665 fn airDivFloor(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2666 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2667 const lhs_id = try self.resolve(bin_op.lhs);
2668 const rhs_id = try self.resolve(bin_op.rhs);
2669 const ty = self.typeOfIndex(inst);
2670 const ty_ref = try self.resolveType(ty, .direct);
2671 const info = self.arithmeticTypeInfo(ty);
2672 switch (info.class) {
2673 .composite_integer => unreachable, // TODO
2674 .integer, .strange_integer => {
2675 const zero_id = try self.constInt(ty_ref, 0);
2676 const one_id = try self.constInt(ty_ref, 1);
2677
2678 // (a ^ b) > 0
2679 const bin_bitwise_id = try self.binOpSimple(ty, lhs_id, rhs_id, .OpBitwiseXor);
2680 const is_positive_id = try self.cmp(.gt, Type.bool, ty, bin_bitwise_id, zero_id);
2681
2682 // a / b
2683 const positive_div_id = try self.arithOp(ty, lhs_id, rhs_id, .OpFDiv, .OpSDiv, .OpUDiv);
2684
2685 // - (abs(a) + abs(b) - 1) / abs(b)
2686 const lhs_abs = try self.abs(ty, ty, lhs_id);
2687 const rhs_abs = try self.abs(ty, ty, rhs_id);
2688 const negative_div_lhs = try self.arithOp(
2689 ty,
2690 try self.arithOp(ty, lhs_abs, rhs_abs, .OpFAdd, .OpIAdd, .OpIAdd),
2691 one_id,
2692 .OpFSub,
2693 .OpISub,
2694 .OpISub,
2695 );
2696 const negative_div_id = try self.arithOp(ty, negative_div_lhs, rhs_abs, .OpFDiv, .OpSDiv, .OpUDiv);
2697 const negated_negative_div_id = self.spv.allocId();
2698 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{
2699 .id_result_type = self.typeId(ty_ref),
2700 .id_result = negated_negative_div_id,
2701 .operand = negative_div_id,
2702 });
2703
2704 const result_id = self.spv.allocId();
2705 try self.func.body.emit(self.spv.gpa, .OpSelect, .{
2706 .id_result_type = self.typeId(ty_ref),
2707 .id_result = result_id,
2708 .condition = is_positive_id,
2709 .object_1 = positive_div_id,
2710 .object_2 = negated_negative_div_id,
2711 });
2712 return result_id;
2713 },
2714 .float => {
2715 const div_id = try self.arithOp(ty, lhs_id, rhs_id, .OpFDiv, .OpSDiv, .OpUDiv);
2716 return try self.floor(ty, div_id);
2717 },
2718 .bool => unreachable,
2719 }
2720 }
2721
2722 fn airFloor(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2723 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
2724 const operand_id = try self.resolve(un_op);
2725 const result_ty = self.typeOfIndex(inst);
2726 return try self.floor(result_ty, operand_id);
2727 }
2728
2729 fn floor(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {
2730 const target = self.getTarget();
2731 const ty_ref = try self.resolveType(ty, .direct);
2732 const ext_inst: Word = switch (target.os.tag) {
2733 .opencl => 25,
2734 .vulkan => 8,
2735 else => unreachable,
2736 };
2737 const set_id = switch (target.os.tag) {
2738 .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"),
2739 .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"),
2740 else => unreachable,
2741 };
2742
2743 const result_id = self.spv.allocId();
2744 try self.func.body.emit(self.spv.gpa, .OpExtInst, .{
2745 .id_result_type = self.typeId(ty_ref),
2746 .id_result = result_id,
2747 .set = set_id,
2748 .instruction = .{ .inst = ext_inst },
2749 .id_ref_4 = &.{operand_id},
2750 });
2751 return result_id;
2752 }
2753
2664 fn airArithOp(2754 fn airArithOp(
2665 self: *DeclGen,2755 self: *DeclGen,
2666 inst: Air.Inst.Index,2756 inst: Air.Inst.Index,
...@@ -2668,7 +2758,6 @@ const DeclGen = struct {...@@ -2668,7 +2758,6 @@ const DeclGen = struct {
2668 comptime sop: Opcode,2758 comptime sop: Opcode,
2669 comptime uop: Opcode,2759 comptime uop: Opcode,
2670 ) !?IdRef {2760 ) !?IdRef {
2671
2672 // LHS and RHS are guaranteed to have the same type, and AIR guarantees2761 // LHS and RHS are guaranteed to have the same type, and AIR guarantees
2673 // the result to be the same as the LHS and RHS, which matches SPIR-V.2762 // the result to be the same as the LHS and RHS, which matches SPIR-V.
2674 const ty = self.typeOfIndex(inst);2763 const ty = self.typeOfIndex(inst);
...@@ -2700,8 +2789,8 @@ const DeclGen = struct {...@@ -2700,8 +2789,8 @@ const DeclGen = struct {
2700 return self.todo("binary operations for composite integers", .{});2789 return self.todo("binary operations for composite integers", .{});
2701 },2790 },
2702 .integer, .strange_integer => switch (info.signedness) {2791 .integer, .strange_integer => switch (info.signedness) {
2703 .signed => @as(usize, 1),2792 .signed => 1,
2704 .unsigned => @as(usize, 2),2793 .unsigned => 2,
2705 },2794 },
2706 .float => 0,2795 .float => 0,
2707 .bool => unreachable,2796 .bool => unreachable,
...@@ -2737,12 +2826,16 @@ const DeclGen = struct {...@@ -2737,12 +2826,16 @@ const DeclGen = struct {
2737 }2826 }
27382827
2739 fn airAbs(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2828 fn airAbs(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2740 const target = self.getTarget();
2741 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2829 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2742 const operand_id = try self.resolve(ty_op.operand);2830 const operand_id = try self.resolve(ty_op.operand);
2743 // Note: operand_ty may be signed, while ty is always unsigned!2831 // Note: operand_ty may be signed, while ty is always unsigned!
2744 const operand_ty = self.typeOf(ty_op.operand);2832 const operand_ty = self.typeOf(ty_op.operand);
2745 const result_ty = self.typeOfIndex(inst);2833 const result_ty = self.typeOfIndex(inst);
2834 return try self.abs(result_ty, operand_ty, operand_id);
2835 }
2836
2837 fn abs(self: *DeclGen, result_ty: Type, operand_ty: Type, operand_id: IdRef) !IdRef {
2838 const target = self.getTarget();
2746 const operand_info = self.arithmeticTypeInfo(operand_ty);2839 const operand_info = self.arithmeticTypeInfo(operand_ty);
27472840
2748 var wip = try self.elementWise(result_ty, false);2841 var wip = try self.elementWise(result_ty, false);
...@@ -2907,6 +3000,61 @@ const DeclGen = struct {...@@ -2907,6 +3000,61 @@ const DeclGen = struct {
2907 );3000 );
2908 }3001 }
29093002
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
2910 fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3058 fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2911 const mod = self.module;3059 const mod = self.module;
2912 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3060 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
...@@ -3692,19 +3840,22 @@ const DeclGen = struct {...@@ -3692,19 +3840,22 @@ const DeclGen = struct {
3692 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3840 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3693 const operand_ty = self.typeOf(ty_op.operand);3841 const operand_ty = self.typeOf(ty_op.operand);
3694 const operand_id = try self.resolve(ty_op.operand);3842 const operand_id = try self.resolve(ty_op.operand);
3695 const operand_info = self.arithmeticTypeInfo(operand_ty);3843 const result_ty = self.typeOfIndex(inst);
3696 const dest_ty = self.typeOfIndex(inst);3844 const result_ty_ref = try self.resolveType(result_ty, .direct);
3697 const dest_ty_id = try self.resolveTypeId(dest_ty);3845 return try self.floatFromInt(result_ty_ref, operand_ty, operand_id);
3846 }
36983847
3848 fn floatFromInt(self: *DeclGen, result_ty_ref: CacheRef, operand_ty: Type, operand_id: IdRef) !IdRef {
3849 const operand_info = self.arithmeticTypeInfo(operand_ty);
3699 const result_id = self.spv.allocId();3850 const result_id = self.spv.allocId();
3700 switch (operand_info.signedness) {3851 switch (operand_info.signedness) {
3701 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{3852 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{
3702 .id_result_type = dest_ty_id,3853 .id_result_type = self.typeId(result_ty_ref),
3703 .id_result = result_id,3854 .id_result = result_id,
3704 .signed_value = operand_id,3855 .signed_value = operand_id,
3705 }),3856 }),
3706 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{3857 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{
3707 .id_result_type = dest_ty_id,3858 .id_result_type = self.typeId(result_ty_ref),
3708 .id_result = result_id,3859 .id_result = result_id,
3709 .unsigned_value = operand_id,3860 .unsigned_value = operand_id,
3710 }),3861 }),
...@@ -3715,19 +3866,22 @@ const DeclGen = struct {...@@ -3715,19 +3866,22 @@ const DeclGen = struct {
3715 fn airIntFromFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3866 fn airIntFromFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3716 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3867 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3717 const operand_id = try self.resolve(ty_op.operand);3868 const operand_id = try self.resolve(ty_op.operand);
3718 const dest_ty = self.typeOfIndex(inst);3869 const result_ty = self.typeOfIndex(inst);
3719 const dest_info = self.arithmeticTypeInfo(dest_ty);3870 return try self.intFromFloat(result_ty, operand_id);
3720 const dest_ty_id = try self.resolveTypeId(dest_ty);3871 }
37213872
3873 fn intFromFloat(self: *DeclGen, result_ty: Type, operand_id: IdRef) !IdRef {
3874 const result_info = self.arithmeticTypeInfo(result_ty);
3875 const result_ty_ref = try self.resolveType(result_ty, .direct);
3722 const result_id = self.spv.allocId();3876 const result_id = self.spv.allocId();
3723 switch (dest_info.signedness) {3877 switch (result_info.signedness) {
3724 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{3878 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{
3725 .id_result_type = dest_ty_id,3879 .id_result_type = self.typeId(result_ty_ref),
3726 .id_result = result_id,3880 .id_result = result_id,
3727 .float_value = operand_id,3881 .float_value = operand_id,
3728 }),3882 }),
3729 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{3883 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{
3730 .id_result_type = dest_ty_id,3884 .id_result_type = self.typeId(result_ty_ref),
3731 .id_result = result_id,3885 .id_result = result_id,
3732 .float_value = operand_id,3886 .float_value = operand_id,
3733 }),3887 }),
...@@ -5237,20 +5391,21 @@ const DeclGen = struct {...@@ -5237,20 +5391,21 @@ const DeclGen = struct {
52375391
5238 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {5392 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
5239 const mod = self.module;5393 const mod = self.module;
5394 const target = self.getTarget();
5240 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5395 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5241 const cond_ty = self.typeOf(pl_op.operand);5396 const cond_ty = self.typeOf(pl_op.operand);
5242 const cond = try self.resolve(pl_op.operand);5397 const cond = try self.resolve(pl_op.operand);
5243 const cond_indirect = try self.convertToIndirect(cond_ty, cond);5398 var cond_indirect = try self.convertToIndirect(cond_ty, cond);
5244 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);5399 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
52455400
5246 const cond_words: u32 = switch (cond_ty.zigTypeTag(mod)) {5401 const cond_words: u32 = switch (cond_ty.zigTypeTag(mod)) {
5247 .Bool => 1,5402 .Bool, .ErrorSet => 1,
5248 .Int => blk: {5403 .Int => blk: {
5249 const bits = cond_ty.intInfo(mod).bits;5404 const bits = cond_ty.intInfo(mod).bits;
5250 const backing_bits = self.backingIntBits(bits) orelse {5405 const backing_bits = self.backingIntBits(bits) orelse {
5251 return self.todo("implement composite int switch", .{});5406 return self.todo("implement composite int switch", .{});
5252 };5407 };
5253 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;5408 break :blk if (backing_bits <= 32) 1 else 2;
5254 },5409 },
5255 .Enum => blk: {5410 .Enum => blk: {
5256 const int_ty = cond_ty.intTagType(mod);5411 const int_ty = cond_ty.intTagType(mod);
...@@ -5258,10 +5413,14 @@ const DeclGen = struct {...@@ -5258,10 +5413,14 @@ const DeclGen = struct {
5258 const backing_bits = self.backingIntBits(int_info.bits) orelse {5413 const backing_bits = self.backingIntBits(int_info.bits) orelse {
5259 return self.todo("implement composite int switch", .{});5414 return self.todo("implement composite int switch", .{});
5260 };5415 };
5261 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;5416 break :blk if (backing_bits <= 32) 1 else 2;
5417 },
5418 .Pointer => blk: {
5419 cond_indirect = try self.intFromPtr(cond_indirect);
5420 break :blk target.ptrBitWidth() / 32;
5262 },5421 },
5263 .ErrorSet => 1,5422 // TODO: Figure out which types apply here, and work around them as we can only do integers.
5264 else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag(mod))}), // TODO: Figure out which types apply here, and work around them as we can only do integers.5423 else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag(mod))}),
5265 };5424 };
52665425
5267 const num_cases = switch_br.data.cases_len;5426 const num_cases = switch_br.data.cases_len;
...@@ -5308,7 +5467,7 @@ const DeclGen = struct {...@@ -5308,7 +5467,7 @@ const DeclGen = struct {
5308 for (0..num_cases) |case_i| {5467 for (0..num_cases) |case_i| {
5309 // SPIR-V needs a literal here, which' width depends on the case condition.5468 // SPIR-V needs a literal here, which' width depends on the case condition.
5310 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);5469 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
5311 const items = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[case.end..][0..case.data.items_len]));5470 const items: []const Air.Inst.Ref = @ptrCast(self.air.extra[case.end..][0..case.data.items_len]);
5312 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];5471 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
5313 extra_index = case.end + case.data.items_len + case_body.len;5472 extra_index = case.end + case.data.items_len + case_body.len;
53145473
...@@ -5316,13 +5475,14 @@ const DeclGen = struct {...@@ -5316,13 +5475,14 @@ const DeclGen = struct {
53165475
5317 for (items) |item| {5476 for (items) |item| {
5318 const value = (try self.air.value(item, mod)) orelse unreachable;5477 const value = (try self.air.value(item, mod)) orelse unreachable;
5319 const int_val = switch (cond_ty.zigTypeTag(mod)) {5478 const int_val: u64 = switch (cond_ty.zigTypeTag(mod)) {
5320 .Bool, .Int => if (cond_ty.isSignedInt(mod)) @as(u64, @bitCast(value.toSignedInt(mod))) else value.toUnsignedInt(mod),5479 .Bool, .Int => if (cond_ty.isSignedInt(mod)) @bitCast(value.toSignedInt(mod)) else value.toUnsignedInt(mod),
5321 .Enum => blk: {5480 .Enum => blk: {
5322 // TODO: figure out of cond_ty is correct (something with enum literals)5481 // TODO: figure out of cond_ty is correct (something with enum literals)
5323 break :blk (try value.intFromEnum(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants5482 break :blk (try value.intFromEnum(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants
5324 },5483 },
5325 .ErrorSet => value.getErrorInt(mod),5484 .ErrorSet => value.getErrorInt(mod),
5485 .Pointer => value.toUnsignedInt(mod),
5326 else => unreachable,5486 else => unreachable,
5327 };5487 };
5328 const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) {5488 const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) {
...@@ -5438,14 +5598,14 @@ const DeclGen = struct {...@@ -5438,14 +5598,14 @@ const DeclGen = struct {
5438 const extra = self.air.extraData(Air.Asm, ty_pl.payload);5598 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
54395599
5440 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;5600 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
5441 const clobbers_len = @as(u31, @truncate(extra.data.flags));5601 const clobbers_len: u31 = @truncate(extra.data.flags);
54425602
5443 if (!is_volatile and self.liveness.isUnused(inst)) return null;5603 if (!is_volatile and self.liveness.isUnused(inst)) return null;
54445604
5445 var extra_i: usize = extra.end;5605 var extra_i: usize = extra.end;
5446 const outputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]));5606 const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]);
5447 extra_i += outputs.len;5607 extra_i += outputs.len;
5448 const inputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]));5608 const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]);
5449 extra_i += inputs.len;5609 extra_i += inputs.len;
54505610
5451 if (outputs.len > 1) {5611 if (outputs.len > 1) {
...@@ -5567,7 +5727,7 @@ const DeclGen = struct {...@@ -5567,7 +5727,7 @@ const DeclGen = struct {
5567 const mod = self.module;5727 const mod = self.module;
5568 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5728 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5569 const extra = self.air.extraData(Air.Call, pl_op.payload);5729 const extra = self.air.extraData(Air.Call, pl_op.payload);
5570 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));5730 const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);
5571 const callee_ty = self.typeOf(pl_op.operand);5731 const callee_ty = self.typeOf(pl_op.operand);
5572 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {5732 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
5573 .Fn => callee_ty,5733 .Fn => callee_ty,
src/codegen/spirv/Assembler.zig+29-9
...@@ -256,10 +256,18 @@ fn todo(self: *Assembler, comptime fmt: []const u8, args: anytype) Error {...@@ -256,10 +256,18 @@ fn todo(self: *Assembler, comptime fmt: []const u8, args: anytype) Error {
256/// If this function returns `error.AssembleFail`, an explanatory256/// If this function returns `error.AssembleFail`, an explanatory
257/// error message has already been emitted into `self.errors`.257/// error message has already been emitted into `self.errors`.
258fn processInstruction(self: *Assembler) !void {258fn processInstruction(self: *Assembler) !void {
259 const result = switch (self.inst.opcode) {259 const result: AsmValue = switch (self.inst.opcode) {
260 .OpEntryPoint => {260 .OpEntryPoint => {
261 return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});261 return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});
262 },262 },
263 .OpExtInstImport => blk: {
264 const set_name_offset = self.inst.operands.items[1].string;
265 const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0);
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) };
270 },
263 else => switch (self.inst.opcode.class()) {271 else => switch (self.inst.opcode.class()) {
264 .TypeDeclaration => try self.processTypeInstruction(),272 .TypeDeclaration => try self.processTypeInstruction(),
265 else => if (try self.processGenericInstruction()) |result|273 else => if (try self.processGenericInstruction()) |result|
...@@ -309,7 +317,7 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {...@@ -309,7 +317,7 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
309 return self.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});317 return self.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});
310 },318 },
311 }319 }
312 break :blk try self.spv.resolve(.{ .float_type = .{ .bits = @as(u16, @intCast(bits)) } });320 break :blk try self.spv.resolve(.{ .float_type = .{ .bits = @intCast(bits) } });
313 },321 },
314 .OpTypeVector => try self.spv.resolve(.{ .vector_type = .{322 .OpTypeVector => try self.spv.resolve(.{ .vector_type = .{
315 .component_type = try self.resolveTypeRef(operands[1].ref_id),323 .component_type = try self.resolveTypeRef(operands[1].ref_id),
...@@ -364,6 +372,7 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue {...@@ -364,6 +372,7 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue {
364 .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes,372 .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes,
365 .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) {373 .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) {
366 .Function => &self.func.prologue,374 .Function => &self.func.prologue,
375 .UniformConstant => &self.spv.sections.types_globals_constants,
367 else => {376 else => {
368 // This is currently disabled because global variables are required to be377 // This is currently disabled because global variables are required to be
369 // emitted in the proper order, and this should be honored in inline assembly378 // emitted in the proper order, and this should be honored in inline assembly
...@@ -473,14 +482,14 @@ fn parseInstruction(self: *Assembler) !void {...@@ -473,14 +482,14 @@ fn parseInstruction(self: *Assembler) !void {
473 self.inst.string_bytes.shrinkRetainingCapacity(0);482 self.inst.string_bytes.shrinkRetainingCapacity(0);
474483
475 const lhs_result_tok = self.currentToken();484 const lhs_result_tok = self.currentToken();
476 const maybe_lhs_result = if (self.eatToken(.result_id_assign)) blk: {485 const maybe_lhs_result: ?AsmValue.Ref = if (self.eatToken(.result_id_assign)) blk: {
477 const name = self.tokenText(lhs_result_tok)[1..];486 const name = self.tokenText(lhs_result_tok)[1..];
478 const entry = try self.value_map.getOrPut(self.gpa, name);487 const entry = try self.value_map.getOrPut(self.gpa, name);
479 try self.expectToken(.equals);488 try self.expectToken(.equals);
480 if (!entry.found_existing) {489 if (!entry.found_existing) {
481 entry.value_ptr.* = .just_declared;490 entry.value_ptr.* = .just_declared;
482 }491 }
483 break :blk @as(AsmValue.Ref, @intCast(entry.index));492 break :blk @intCast(entry.index);
484 } else null;493 } else null;
485494
486 const opcode_tok = self.currentToken();495 const opcode_tok = self.currentToken();
...@@ -550,6 +559,7 @@ fn parseOperand(self: *Assembler, kind: spec.OperandKind) Error!void {...@@ -550,6 +559,7 @@ fn parseOperand(self: *Assembler, kind: spec.OperandKind) Error!void {
550 .LiteralInteger => try self.parseLiteralInteger(),559 .LiteralInteger => try self.parseLiteralInteger(),
551 .LiteralString => try self.parseString(),560 .LiteralString => try self.parseString(),
552 .LiteralContextDependentNumber => try self.parseContextDependentNumber(),561 .LiteralContextDependentNumber => try self.parseContextDependentNumber(),
562 .LiteralExtInstInteger => try self.parseLiteralExtInstInteger(),
553 .PairIdRefIdRef => try self.parsePhiSource(),563 .PairIdRefIdRef => try self.parsePhiSource(),
554 else => return self.todo("parse operand of type {s}", .{@tagName(kind)}),564 else => return self.todo("parse operand of type {s}", .{@tagName(kind)}),
555 },565 },
...@@ -641,7 +651,7 @@ fn parseRefId(self: *Assembler) !void {...@@ -641,7 +651,7 @@ fn parseRefId(self: *Assembler) !void {
641 entry.value_ptr.* = .unresolved_forward_reference;651 entry.value_ptr.* = .unresolved_forward_reference;
642 }652 }
643653
644 const index = @as(AsmValue.Ref, @intCast(entry.index));654 const index: AsmValue.Ref = @intCast(entry.index);
645 try self.inst.operands.append(self.gpa, .{ .ref_id = index });655 try self.inst.operands.append(self.gpa, .{ .ref_id = index });
646}656}
647657
...@@ -660,6 +670,16 @@ fn parseLiteralInteger(self: *Assembler) !void {...@@ -660,6 +670,16 @@ fn parseLiteralInteger(self: *Assembler) !void {
660 try self.inst.operands.append(self.gpa, .{ .literal32 = value });670 try self.inst.operands.append(self.gpa, .{ .literal32 = value });
661}671}
662672
673fn parseLiteralExtInstInteger(self: *Assembler) !void {
674 const tok = self.currentToken();
675 try self.expectToken(.value);
676 const text = self.tokenText(tok);
677 const value = std.fmt.parseInt(u32, text, 0) catch {
678 return self.fail(tok.start, "'{s}' is not a valid 32-bit integer literal", .{text});
679 };
680 try self.inst.operands.append(self.gpa, .{ .literal32 = value });
681}
682
663fn parseString(self: *Assembler) !void {683fn parseString(self: *Assembler) !void {
664 const tok = self.currentToken();684 const tok = self.currentToken();
665 try self.expectToken(.string);685 try self.expectToken(.string);
...@@ -673,7 +693,7 @@ fn parseString(self: *Assembler) !void {...@@ -673,7 +693,7 @@ fn parseString(self: *Assembler) !void {
673 else693 else
674 text[1..];694 text[1..];
675695
676 const string_offset = @as(u32, @intCast(self.inst.string_bytes.items.len));696 const string_offset: u32 = @intCast(self.inst.string_bytes.items.len);
677 try self.inst.string_bytes.ensureUnusedCapacity(self.gpa, literal.len + 1);697 try self.inst.string_bytes.ensureUnusedCapacity(self.gpa, literal.len + 1);
678 self.inst.string_bytes.appendSliceAssumeCapacity(literal);698 self.inst.string_bytes.appendSliceAssumeCapacity(literal);
679 self.inst.string_bytes.appendAssumeCapacity(0);699 self.inst.string_bytes.appendAssumeCapacity(0);
...@@ -730,9 +750,9 @@ fn parseContextDependentInt(self: *Assembler, signedness: std.builtin.Signedness...@@ -730,9 +750,9 @@ fn parseContextDependentInt(self: *Assembler, signedness: std.builtin.Signedness
730750
731 // Note, we store the sign-extended version here.751 // Note, we store the sign-extended version here.
732 if (width <= @bitSizeOf(spec.Word)) {752 if (width <= @bitSizeOf(spec.Word)) {
733 try self.inst.operands.append(self.gpa, .{ .literal32 = @as(u32, @truncate(@as(u128, @bitCast(int)))) });753 try self.inst.operands.append(self.gpa, .{ .literal32 = @truncate(@as(u128, @bitCast(int))) });
734 } else {754 } else {
735 try self.inst.operands.append(self.gpa, .{ .literal64 = @as(u64, @truncate(@as(u128, @bitCast(int)))) });755 try self.inst.operands.append(self.gpa, .{ .literal64 = @truncate(@as(u128, @bitCast(int))) });
736 }756 }
737 return;757 return;
738 }758 }
...@@ -753,7 +773,7 @@ fn parseContextDependentFloat(self: *Assembler, comptime width: u16) !void {...@@ -753,7 +773,7 @@ fn parseContextDependentFloat(self: *Assembler, comptime width: u16) !void {
753 return self.fail(tok.start, "'{s}' is not a valid {}-bit float literal", .{ text, width });773 return self.fail(tok.start, "'{s}' is not a valid {}-bit float literal", .{ text, width });
754 };774 };
755775
756 const float_bits = @as(Int, @bitCast(value));776 const float_bits: Int = @bitCast(value);
757 if (width <= @bitSizeOf(spec.Word)) {777 if (width <= @bitSizeOf(spec.Word)) {
758 try self.inst.operands.append(self.gpa, .{ .literal32 = float_bits });778 try self.inst.operands.append(self.gpa, .{ .literal32 = float_bits });
759 } else {779 } else {
src/codegen/spirv/Module.zig+4-4
...@@ -429,8 +429,8 @@ pub fn constInt(self: *Module, ty_ref: CacheRef, value: anytype) !IdRef {...@@ -429,8 +429,8 @@ pub fn constInt(self: *Module, ty_ref: CacheRef, value: anytype) !IdRef {
429 return try self.resolveId(.{ .int = .{429 return try self.resolveId(.{ .int = .{
430 .ty = ty_ref,430 .ty = ty_ref,
431 .value = switch (ty.signedness) {431 .value = switch (ty.signedness) {
432 .signed => Value{ .int64 = @as(i64, @intCast(value)) },432 .signed => Value{ .int64 = @intCast(value) },
433 .unsigned => Value{ .uint64 = @as(u64, @intCast(value)) },433 .unsigned => Value{ .uint64 = @intCast(value) },
434 },434 },
435 } });435 } });
436}436}
...@@ -500,9 +500,9 @@ pub fn declPtr(self: *Module, index: Decl.Index) *Decl {...@@ -500,9 +500,9 @@ pub fn declPtr(self: *Module, index: Decl.Index) *Decl {
500500
501/// Declare ALL dependencies for a decl.501/// Declare ALL dependencies for a decl.
502pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl.Index) !void {502pub fn declareDeclDeps(self: *Module, decl_index: Decl.Index, deps: []const Decl.Index) !void {
503 const begin_dep = @as(u32, @intCast(self.decl_deps.items.len));503 const begin_dep: u32 = @intCast(self.decl_deps.items.len);
504 try self.decl_deps.appendSlice(self.gpa, deps);504 try self.decl_deps.appendSlice(self.gpa, deps);
505 const end_dep = @as(u32, @intCast(self.decl_deps.items.len));505 const end_dep: u32 = @intCast(self.decl_deps.items.len);
506506
507 const decl = self.declPtr(decl_index);507 const decl = self.declPtr(decl_index);
508 decl.begin_dep = begin_dep;508 decl.begin_dep = begin_dep;
src/codegen/spirv/Section.zig+10-10
...@@ -115,8 +115,8 @@ pub fn writeWords(section: *Section, words: []const Word) void {...@@ -115,8 +115,8 @@ pub fn writeWords(section: *Section, words: []const Word) void {
115115
116pub fn writeDoubleWord(section: *Section, dword: DoubleWord) void {116pub fn writeDoubleWord(section: *Section, dword: DoubleWord) void {
117 section.writeWords(&.{117 section.writeWords(&.{
118 @as(Word, @truncate(dword)),118 @truncate(dword),
119 @as(Word, @truncate(dword >> @bitSizeOf(Word))),119 @truncate(dword >> @bitSizeOf(Word)),
120 });120 });
121}121}
122122
...@@ -196,12 +196,12 @@ fn writeString(section: *Section, str: []const u8) void {...@@ -196,12 +196,12 @@ fn writeString(section: *Section, str: []const u8) void {
196196
197fn writeContextDependentNumber(section: *Section, operand: spec.LiteralContextDependentNumber) void {197fn writeContextDependentNumber(section: *Section, operand: spec.LiteralContextDependentNumber) void {
198 switch (operand) {198 switch (operand) {
199 .int32 => |int| section.writeWord(@as(Word, @bitCast(int))),199 .int32 => |int| section.writeWord(@bitCast(int)),
200 .uint32 => |int| section.writeWord(@as(Word, @bitCast(int))),200 .uint32 => |int| section.writeWord(@bitCast(int)),
201 .int64 => |int| section.writeDoubleWord(@as(DoubleWord, @bitCast(int))),201 .int64 => |int| section.writeDoubleWord(@bitCast(int)),
202 .uint64 => |int| section.writeDoubleWord(@as(DoubleWord, @bitCast(int))),202 .uint64 => |int| section.writeDoubleWord(@bitCast(int)),
203 .float32 => |float| section.writeWord(@as(Word, @bitCast(float))),203 .float32 => |float| section.writeWord(@bitCast(float)),
204 .float64 => |float| section.writeDoubleWord(@as(DoubleWord, @bitCast(float))),204 .float64 => |float| section.writeDoubleWord(@bitCast(float)),
205 }205 }
206}206}
207207
...@@ -274,8 +274,8 @@ fn operandSize(comptime Operand: type, operand: Operand) usize {...@@ -274,8 +274,8 @@ fn operandSize(comptime Operand: type, operand: Operand) usize {
274 spec.LiteralString => std.math.divCeil(usize, operand.len + 1, @sizeOf(Word)) catch unreachable, // Add one for zero-terminator274 spec.LiteralString => std.math.divCeil(usize, operand.len + 1, @sizeOf(Word)) catch unreachable, // Add one for zero-terminator
275275
276 spec.LiteralContextDependentNumber => switch (operand) {276 spec.LiteralContextDependentNumber => switch (operand) {
277 .int32, .uint32, .float32 => @as(usize, 1),277 .int32, .uint32, .float32 => 1,
278 .int64, .uint64, .float64 => @as(usize, 2),278 .int64, .uint64, .float64 => 2,
279 },279 },
280280
281 // TODO: Where this type is used (OpSpecConstantOp) is currently not correct in the spec281 // TODO: Where this type is used (OpSpecConstantOp) is currently not correct in the spec
test/behavior/floatop.zig-3
...@@ -1089,7 +1089,6 @@ test "@floor f16" {...@@ -1089,7 +1089,6 @@ test "@floor f16" {
1089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1091 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1091 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1092 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10931092
1094 try testFloor(f16);1093 try testFloor(f16);
1095 try comptime testFloor(f16);1094 try comptime testFloor(f16);
...@@ -1100,7 +1099,6 @@ test "@floor f32/f64" {...@@ -1100,7 +1099,6 @@ test "@floor f32/f64" {
1100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1102 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1101 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11041102
1105 try testFloor(f32);1103 try testFloor(f32);
1106 try comptime testFloor(f32);1104 try comptime testFloor(f32);
...@@ -1162,7 +1160,6 @@ fn testFloor(comptime T: type) !void {...@@ -1162,7 +1160,6 @@ fn testFloor(comptime T: type) !void {
1162test "@floor with vectors" {1160test "@floor with vectors" {
1163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1165 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1166 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1163 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1167 if (builtin.zig_backend == .stage2_x86_64 and1164 if (builtin.zig_backend == .stage2_x86_64 and
1168 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;1165 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
test/behavior/for.zig-1
...@@ -226,7 +226,6 @@ test "else continue outer for" {...@@ -226,7 +226,6 @@ test "else continue outer for" {
226226
227test "for loop with else branch" {227test "for loop with else branch" {
228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
229 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
230229
231 {230 {
232 var x = [_]u32{ 1, 2 };231 var x = [_]u32{ 1, 2 };
test/behavior/hasdecl.zig-4
...@@ -12,8 +12,6 @@ const Bar = struct {...@@ -12,8 +12,6 @@ const Bar = struct {
12};12};
1313
14test "@hasDecl" {14test "@hasDecl" {
15 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
16
17 try expect(@hasDecl(Foo, "public_thing"));15 try expect(@hasDecl(Foo, "public_thing"));
18 try expect(!@hasDecl(Foo, "private_thing"));16 try expect(!@hasDecl(Foo, "private_thing"));
19 try expect(!@hasDecl(Foo, "no_thing"));17 try expect(!@hasDecl(Foo, "no_thing"));
...@@ -24,8 +22,6 @@ test "@hasDecl" {...@@ -24,8 +22,6 @@ test "@hasDecl" {
24}22}
2523
26test "@hasDecl using a sliced string literal" {24test "@hasDecl using a sliced string literal" {
27 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
28
29 try expect(@hasDecl(@This(), "std") == true);25 try expect(@hasDecl(@This(), "std") == true);
30 try expect(@hasDecl(@This(), "std"[0..0]) == false);26 try expect(@hasDecl(@This(), "std"[0..0]) == false);
31 try expect(@hasDecl(@This(), "std"[0..1]) == false);27 try expect(@hasDecl(@This(), "std"[0..1]) == false);
test/behavior/int_div.zig-1
...@@ -6,7 +6,6 @@ test "integer division" {...@@ -6,7 +6,6 @@ test "integer division" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
109
11 try testDivision();10 try testDivision();
12 try comptime testDivision();11 try comptime testDivision();
test/behavior/math.zig-3
...@@ -788,7 +788,6 @@ test "small int addition" {...@@ -788,7 +788,6 @@ test "small int addition" {
788test "basic @mulWithOverflow" {788test "basic @mulWithOverflow" {
789 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO789 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
792791
793 {792 {
794 var a: u8 = 86;793 var a: u8 = 86;
...@@ -821,7 +820,6 @@ test "basic @mulWithOverflow" {...@@ -821,7 +820,6 @@ test "basic @mulWithOverflow" {
821test "extensive @mulWithOverflow" {820test "extensive @mulWithOverflow" {
822 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO821 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
823 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO822 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
824 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
825823
826 {824 {
827 var a: u5 = 3;825 var a: u5 = 3;
...@@ -998,7 +996,6 @@ test "@mulWithOverflow bitsize > 32" {...@@ -998,7 +996,6 @@ test "@mulWithOverflow bitsize > 32" {
998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO996 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
999 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO997 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1000 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO998 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1001 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1002999
1003 {1000 {
1004 var a: u62 = 3;1001 var a: u62 = 3;
test/behavior/switch.zig-1
...@@ -640,7 +640,6 @@ test "switch prong pointer capture alignment" {...@@ -640,7 +640,6 @@ test "switch prong pointer capture alignment" {
640test "switch on pointer type" {640test "switch on pointer type" {
641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
643 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
644643
645 const S = struct {644 const S = struct {
646 const X = struct {645 const X = struct {
test/behavior/vector.zig-1
...@@ -1136,7 +1136,6 @@ test "@mulWithOverflow" {...@@ -1136,7 +1136,6 @@ test "@mulWithOverflow" {
1136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1139 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11401139
1141 const S = struct {1140 const S = struct {
1142 fn doTheTest() !void {1141 fn doTheTest() !void {