| author | |
| committer | |
| log | 7634a115c50ef66edbdd5644c4ba310eb31e6343 |
| tree | b8be56f0db16691e2939e87bac1222ba2c9fd4a8 |
| parent | aebf20cc9a0469a778d6276d3797525660746e91 |
| parent | 25111061504a652bfed45b26252349f363b109af |
| signature |
spirv: more vector operations37 files changed, 956 insertions(+), 516 deletions(-)
lib/std/mem.zig+11-1| ... | @@ -632,10 +632,16 @@ test "lessThan" { | ... | @@ -632,10 +632,16 @@ test "lessThan" { |
| 632 | try testing.expect(lessThan(u8, "", "a")); | 632 | try testing.expect(lessThan(u8, "", "a")); |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | const backend_can_use_eql_bytes = switch (builtin.zig_backend) { | ||
| 636 | // The SPIR-V backend does not support the optimized path yet. | ||
| 637 | .stage2_spirv64 => false, | ||
| 638 | else => true, | ||
| 639 | }; | ||
| 640 | |||
| 635 | /// Compares two slices and returns whether they are equal. | 641 | /// Compares two slices and returns whether they are equal. |
| 636 | pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | 642 | pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 637 | if (@sizeOf(T) == 0) return true; | 643 | if (@sizeOf(T) == 0) return true; |
| 638 | if (!@inComptime() and std.meta.hasUniqueRepresentation(T)) return eqlBytes(sliceAsBytes(a), sliceAsBytes(b)); | 644 | if (!@inComptime() and std.meta.hasUniqueRepresentation(T) and backend_can_use_eql_bytes) return eqlBytes(sliceAsBytes(a), sliceAsBytes(b)); |
| 639 | 645 | ||
| 640 | if (a.len != b.len) return false; | 646 | if (a.len != b.len) return false; |
| 641 | if (a.len == 0 or a.ptr == b.ptr) return true; | 647 | if (a.len == 0 or a.ptr == b.ptr) return true; |
| ... | @@ -648,6 +654,10 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | ... | @@ -648,6 +654,10 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 648 | 654 | ||
| 649 | /// std.mem.eql heavily optimized for slices of bytes. | 655 | /// std.mem.eql heavily optimized for slices of bytes. |
| 650 | fn eqlBytes(a: []const u8, b: []const u8) bool { | 656 | fn eqlBytes(a: []const u8, b: []const u8) bool { |
| 657 | if (!backend_can_use_eql_bytes) { | ||
| 658 | return eql(u8, a, b); | ||
| 659 | } | ||
| 660 | |||
| 651 | if (a.len != b.len) return false; | 661 | if (a.len != b.len) return false; |
| 652 | if (a.len == 0 or a.ptr == b.ptr) return true; | 662 | if (a.len == 0 or a.ptr == b.ptr) return true; |
| 653 | 663 |
src/codegen/spirv.zig+891-433| ... | @@ -373,8 +373,9 @@ const DeclGen = struct { | ... | @@ -373,8 +373,9 @@ const DeclGen = struct { |
| 373 | /// For `composite_integer` this is 0 (TODO) | 373 | /// For `composite_integer` this is 0 (TODO) |
| 374 | backing_bits: u16, | 374 | backing_bits: u16, |
| 375 | 375 | ||
| 376 | /// Whether the type is a vector. | 376 | /// Null if this type is a scalar, or the length |
| 377 | is_vector: bool, | 377 | /// of the vector otherwise. |
| 378 | vector_len: ?u32, | ||
| 378 | 379 | ||
| 379 | /// Whether the inner type is signed. Only relevant for integers. | 380 | /// Whether the inner type is signed. Only relevant for integers. |
| 380 | signedness: std.builtin.Signedness, | 381 | signedness: std.builtin.Signedness, |
| ... | @@ -597,32 +598,37 @@ const DeclGen = struct { | ... | @@ -597,32 +598,37 @@ const DeclGen = struct { |
| 597 | return self.backingIntBits(ty) == null; | 598 | return self.backingIntBits(ty) == null; |
| 598 | } | 599 | } |
| 599 | 600 | ||
| 600 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo { | 601 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo { |
| 601 | const mod = self.module; | 602 | const mod = self.module; |
| 602 | const target = self.getTarget(); | 603 | const target = self.getTarget(); |
| 603 | return switch (ty.zigTypeTag(mod)) { | 604 | var scalar_ty = ty.scalarType(mod); |
| 605 | if (scalar_ty.zigTypeTag(mod) == .Enum) { | ||
| 606 | scalar_ty = scalar_ty.intTagType(mod); | ||
| 607 | } | ||
| 608 | const vector_len = if (ty.isVector(mod)) ty.vectorLen(mod) else null; | ||
| 609 | return switch (scalar_ty.zigTypeTag(mod)) { | ||
| 604 | .Bool => ArithmeticTypeInfo{ | 610 | .Bool => ArithmeticTypeInfo{ |
| 605 | .bits = 1, // Doesn't matter for this class. | 611 | .bits = 1, // Doesn't matter for this class. |
| 606 | .backing_bits = self.backingIntBits(1).?, | 612 | .backing_bits = self.backingIntBits(1).?, |
| 607 | .is_vector = false, | 613 | .vector_len = vector_len, |
| 608 | .signedness = .unsigned, // Technically, but doesn't matter for this class. | 614 | .signedness = .unsigned, // Technically, but doesn't matter for this class. |
| 609 | .class = .bool, | 615 | .class = .bool, |
| 610 | }, | 616 | }, |
| 611 | .Float => ArithmeticTypeInfo{ | 617 | .Float => ArithmeticTypeInfo{ |
| 612 | .bits = ty.floatBits(target), | 618 | .bits = scalar_ty.floatBits(target), |
| 613 | .backing_bits = ty.floatBits(target), // TODO: F80? | 619 | .backing_bits = scalar_ty.floatBits(target), // TODO: F80? |
| 614 | .is_vector = false, | 620 | .vector_len = vector_len, |
| 615 | .signedness = .signed, // Technically, but doesn't matter for this class. | 621 | .signedness = .signed, // Technically, but doesn't matter for this class. |
| 616 | .class = .float, | 622 | .class = .float, |
| 617 | }, | 623 | }, |
| 618 | .Int => blk: { | 624 | .Int => blk: { |
| 619 | const int_info = ty.intInfo(mod); | 625 | const int_info = scalar_ty.intInfo(mod); |
| 620 | // TODO: Maybe it's useful to also return this value. | 626 | // TODO: Maybe it's useful to also return this value. |
| 621 | const maybe_backing_bits = self.backingIntBits(int_info.bits); | 627 | const maybe_backing_bits = self.backingIntBits(int_info.bits); |
| 622 | break :blk ArithmeticTypeInfo{ | 628 | break :blk ArithmeticTypeInfo{ |
| 623 | .bits = int_info.bits, | 629 | .bits = int_info.bits, |
| 624 | .backing_bits = maybe_backing_bits orelse 0, | 630 | .backing_bits = maybe_backing_bits orelse 0, |
| 625 | .is_vector = false, | 631 | .vector_len = vector_len, |
| 626 | .signedness = int_info.signedness, | 632 | .signedness = int_info.signedness, |
| 627 | .class = if (maybe_backing_bits) |backing_bits| | 633 | .class = if (maybe_backing_bits) |backing_bits| |
| 628 | if (backing_bits == int_info.bits) | 634 | if (backing_bits == int_info.bits) |
| ... | @@ -633,22 +639,9 @@ const DeclGen = struct { | ... | @@ -633,22 +639,9 @@ const DeclGen = struct { |
| 633 | .composite_integer, | 639 | .composite_integer, |
| 634 | }; | 640 | }; |
| 635 | }, | 641 | }, |
| 636 | .Enum => return self.arithmeticTypeInfo(ty.intTagType(mod)), | 642 | .Enum => unreachable, |
| 637 | // As of yet, there is no vector support in the self-hosted compiler. | 643 | .Vector => unreachable, |
| 638 | .Vector => blk: { | 644 | else => unreachable, // Unhandled arithmetic type |
| 639 | const child_type = ty.childType(mod); | ||
| 640 | const child_ty_info = try self.arithmeticTypeInfo(child_type); | ||
| 641 | break :blk ArithmeticTypeInfo{ | ||
| 642 | .bits = child_ty_info.bits, | ||
| 643 | .backing_bits = child_ty_info.backing_bits, | ||
| 644 | .is_vector = true, | ||
| 645 | .signedness = child_ty_info.signedness, | ||
| 646 | .class = child_ty_info.class, | ||
| 647 | }; | ||
| 648 | }, | ||
| 649 | // TODO: For which types is this the case? | ||
| 650 | // else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), | ||
| 651 | else => unreachable, | ||
| 652 | }; | 645 | }; |
| 653 | } | 646 | } |
| 654 | 647 | ||
| ... | @@ -685,6 +678,18 @@ const DeclGen = struct { | ... | @@ -685,6 +678,18 @@ const DeclGen = struct { |
| 685 | } | 678 | } |
| 686 | } | 679 | } |
| 687 | 680 | ||
| 681 | /// Emits a float constant | ||
| 682 | fn constFloat(self: *DeclGen, ty_ref: CacheRef, value: f128) !IdRef { | ||
| 683 | const ty = self.spv.cache.lookup(ty_ref).float_type; | ||
| 684 | return switch (ty.bits) { | ||
| 685 | 16 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float16 = @floatCast(value) } } }), | ||
| 686 | 32 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float32 = @floatCast(value) } } }), | ||
| 687 | 64 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float64 = @floatCast(value) } } }), | ||
| 688 | 80, 128 => unreachable, // TODO | ||
| 689 | else => unreachable, | ||
| 690 | }; | ||
| 691 | } | ||
| 692 | |||
| 688 | /// Construct a struct at runtime. | 693 | /// Construct a struct at runtime. |
| 689 | /// ty must be a struct type. | 694 | /// ty must be a struct type. |
| 690 | /// Constituents should be in `indirect` representation (as the elements of a struct should be). | 695 | /// Constituents should be in `indirect` representation (as the elements of a struct should be). |
| ... | @@ -1760,6 +1765,92 @@ const DeclGen = struct { | ... | @@ -1760,6 +1765,92 @@ const DeclGen = struct { |
| 1760 | return union_layout; | 1765 | return union_layout; |
| 1761 | } | 1766 | } |
| 1762 | 1767 | ||
| 1768 | /// This structure is used as helper for element-wise operations. It is intended | ||
| 1769 | /// to be used with both vectors and single elements. | ||
| 1770 | const WipElementWise = struct { | ||
| 1771 | dg: *DeclGen, | ||
| 1772 | result_ty: Type, | ||
| 1773 | /// Always in direct representation. | ||
| 1774 | result_ty_ref: CacheRef, | ||
| 1775 | scalar_ty: Type, | ||
| 1776 | /// Always in direct representation. | ||
| 1777 | scalar_ty_ref: CacheRef, | ||
| 1778 | scalar_ty_id: IdRef, | ||
| 1779 | /// True if the input is actually a vector type. | ||
| 1780 | is_vector: bool, | ||
| 1781 | /// The element-wise operation should fill these results before calling finalize(). | ||
| 1782 | /// These should all be in **direct** representation! `finalize()` will convert | ||
| 1783 | /// them to indirect if required. | ||
| 1784 | results: []IdRef, | ||
| 1785 | |||
| 1786 | fn deinit(wip: *WipElementWise) void { | ||
| 1787 | wip.dg.gpa.free(wip.results); | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | /// Utility function to extract the element at a particular index in an | ||
| 1791 | /// input vector. This type is expected to be a vector if `wip.is_vector`, and | ||
| 1792 | /// a scalar otherwise. | ||
| 1793 | fn elementAt(wip: WipElementWise, ty: Type, value: IdRef, index: usize) !IdRef { | ||
| 1794 | const mod = wip.dg.module; | ||
| 1795 | if (wip.is_vector) { | ||
| 1796 | assert(ty.isVector(mod)); | ||
| 1797 | return try wip.dg.extractField(ty.childType(mod), value, @intCast(index)); | ||
| 1798 | } else { | ||
| 1799 | assert(!ty.isVector(mod)); | ||
| 1800 | assert(index == 0); | ||
| 1801 | return value; | ||
| 1802 | } | ||
| 1803 | } | ||
| 1804 | |||
| 1805 | /// Turns the results of this WipElementWise into a result. This can either | ||
| 1806 | /// be a vector or single element, depending on `result_ty`. | ||
| 1807 | /// After calling this function, this WIP is no longer usable. | ||
| 1808 | /// Results is in `direct` representation. | ||
| 1809 | fn finalize(wip: *WipElementWise) !IdRef { | ||
| 1810 | if (wip.is_vector) { | ||
| 1811 | // Convert all the constituents to indirect, as required for the array. | ||
| 1812 | for (wip.results) |*result| { | ||
| 1813 | result.* = try wip.dg.convertToIndirect(wip.scalar_ty, result.*); | ||
| 1814 | } | ||
| 1815 | return try wip.dg.constructArray(wip.result_ty, wip.results); | ||
| 1816 | } else { | ||
| 1817 | return wip.results[0]; | ||
| 1818 | } | ||
| 1819 | } | ||
| 1820 | |||
| 1821 | /// Allocate a result id at a particular index, and return it. | ||
| 1822 | fn allocId(wip: *WipElementWise, index: usize) IdRef { | ||
| 1823 | assert(wip.is_vector or index == 0); | ||
| 1824 | wip.results[index] = wip.dg.spv.allocId(); | ||
| 1825 | return wip.results[index]; | ||
| 1826 | } | ||
| 1827 | }; | ||
| 1828 | |||
| 1829 | /// Create a new element-wise operation. | ||
| 1830 | fn elementWise(self: *DeclGen, result_ty: Type) !WipElementWise { | ||
| 1831 | const mod = self.module; | ||
| 1832 | // For now, this operation also reasons in terms of `.direct` representation. | ||
| 1833 | const result_ty_ref = try self.resolveType(result_ty, .direct); | ||
| 1834 | const is_vector = result_ty.isVector(mod); | ||
| 1835 | const num_results = if (is_vector) result_ty.vectorLen(mod) else 1; | ||
| 1836 | const results = try self.gpa.alloc(IdRef, num_results); | ||
| 1837 | for (results) |*result| result.* = undefined; | ||
| 1838 | |||
| 1839 | const scalar_ty = result_ty.scalarType(mod); | ||
| 1840 | const scalar_ty_ref = try self.resolveType(scalar_ty, .direct); | ||
| 1841 | |||
| 1842 | return .{ | ||
| 1843 | .dg = self, | ||
| 1844 | .result_ty = result_ty, | ||
| 1845 | .result_ty_ref = result_ty_ref, | ||
| 1846 | .scalar_ty = scalar_ty, | ||
| 1847 | .scalar_ty_ref = scalar_ty_ref, | ||
| 1848 | .scalar_ty_id = self.typeId(scalar_ty_ref), | ||
| 1849 | .is_vector = is_vector, | ||
| 1850 | .results = results, | ||
| 1851 | }; | ||
| 1852 | } | ||
| 1853 | |||
| 1763 | /// The SPIR-V backend is not yet advanced enough to support the std testing infrastructure. | 1854 | /// The SPIR-V backend is not yet advanced enough to support the std testing infrastructure. |
| 1764 | /// In order to be able to run tests, we "temporarily" lower test kernels into separate entry- | 1855 | /// In order to be able to run tests, we "temporarily" lower test kernels into separate entry- |
| 1765 | /// points. The test executor will then be able to invoke these to run the tests. | 1856 | /// points. The test executor will then be able to invoke these to run the tests. |
| ... | @@ -2081,25 +2172,31 @@ const DeclGen = struct { | ... | @@ -2081,25 +2172,31 @@ const DeclGen = struct { |
| 2081 | const air_tags = self.air.instructions.items(.tag); | 2172 | const air_tags = self.air.instructions.items(.tag); |
| 2082 | const maybe_result_id: ?IdRef = switch (air_tags[@intFromEnum(inst)]) { | 2173 | const maybe_result_id: ?IdRef = switch (air_tags[@intFromEnum(inst)]) { |
| 2083 | // zig fmt: off | 2174 | // zig fmt: off |
| 2084 | .add, .add_wrap => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd, true), | 2175 | .add, .add_wrap, .add_optimized => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), |
| 2085 | .sub, .sub_wrap => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub, true), | 2176 | .sub, .sub_wrap, .sub_optimized => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| 2086 | .mul, .mul_wrap => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul, true), | 2177 | .mul, .mul_wrap, .mul_optimized => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul), |
| 2178 | |||
| 2179 | .abs => try self.airAbs(inst), | ||
| 2087 | 2180 | ||
| 2088 | .div_float, | 2181 | .div_float, |
| 2089 | .div_float_optimized, | 2182 | .div_float_optimized, |
| 2090 | // TODO: Check that this is the right operation. | 2183 | // TODO: Check that this is the right operation. |
| 2091 | .div_trunc, | 2184 | .div_trunc, |
| 2092 | .div_trunc_optimized, | 2185 | .div_trunc_optimized, |
| 2093 | => try self.airArithOp(inst, .OpFDiv, .OpSDiv, .OpUDiv, false), | 2186 | => try self.airArithOp(inst, .OpFDiv, .OpSDiv, .OpUDiv), |
| 2094 | // TODO: Check if this is the right operation | 2187 | // TODO: Check if this is the right operation |
| 2095 | // TODO: Make airArithOp for rem not emit a mask for the LHS. | ||
| 2096 | .rem, | 2188 | .rem, |
| 2097 | .rem_optimized, | 2189 | .rem_optimized, |
| 2098 | => try self.airArithOp(inst, .OpFRem, .OpSRem, .OpSRem, false), | 2190 | => try self.airArithOp(inst, .OpFRem, .OpSRem, .OpSRem), |
| 2099 | 2191 | ||
| 2100 | .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan), | 2192 | .add_with_overflow => try self.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan), |
| 2101 | .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan), | 2193 | .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan), |
| 2194 | .shl_with_overflow => try self.airShlOverflow(inst), | ||
| 2102 | 2195 | ||
| 2196 | .mul_add => try self.airMulAdd(inst), | ||
| 2197 | |||
| 2198 | .splat => try self.airSplat(inst), | ||
| 2199 | .reduce, .reduce_optimized => try self.airReduce(inst), | ||
| 2103 | .shuffle => try self.airShuffle(inst), | 2200 | .shuffle => try self.airShuffle(inst), |
| 2104 | 2201 | ||
| 2105 | .ptr_add => try self.airPtrAdd(inst), | 2202 | .ptr_add => try self.airPtrAdd(inst), |
| ... | @@ -2111,7 +2208,8 @@ const DeclGen = struct { | ... | @@ -2111,7 +2208,8 @@ const DeclGen = struct { |
| 2111 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), | 2208 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), |
| 2112 | .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr), | 2209 | .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr), |
| 2113 | 2210 | ||
| 2114 | .shl => try self.airShift(inst, .OpShiftLeftLogical), | 2211 | .shl, .shl_exact => try self.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical), |
| 2212 | .shr, .shr_exact => try self.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic), | ||
| 2115 | 2213 | ||
| 2116 | .min => try self.airMinMax(inst, .lt), | 2214 | .min => try self.airMinMax(inst, .lt), |
| 2117 | .max => try self.airMinMax(inst, .gt), | 2215 | .max => try self.airMinMax(inst, .gt), |
| ... | @@ -2121,6 +2219,7 @@ const DeclGen = struct { | ... | @@ -2121,6 +2219,7 @@ const DeclGen = struct { |
| 2121 | .int_from_ptr => try self.airIntFromPtr(inst), | 2219 | .int_from_ptr => try self.airIntFromPtr(inst), |
| 2122 | .float_from_int => try self.airFloatFromInt(inst), | 2220 | .float_from_int => try self.airFloatFromInt(inst), |
| 2123 | .int_from_float => try self.airIntFromFloat(inst), | 2221 | .int_from_float => try self.airIntFromFloat(inst), |
| 2222 | .int_from_bool => try self.airIntFromBool(inst), | ||
| 2124 | .fpext, .fptrunc => try self.airFloatCast(inst), | 2223 | .fpext, .fptrunc => try self.airFloatCast(inst), |
| 2125 | .not => try self.airNot(inst), | 2224 | .not => try self.airNot(inst), |
| 2126 | 2225 | ||
| ... | @@ -2137,6 +2236,8 @@ const DeclGen = struct { | ... | @@ -2137,6 +2236,8 @@ const DeclGen = struct { |
| 2137 | .ptr_elem_val => try self.airPtrElemVal(inst), | 2236 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 2138 | .array_elem_val => try self.airArrayElemVal(inst), | 2237 | .array_elem_val => try self.airArrayElemVal(inst), |
| 2139 | 2238 | ||
| 2239 | .vector_store_elem => return self.airVectorStoreElem(inst), | ||
| 2240 | |||
| 2140 | .set_union_tag => return self.airSetUnionTag(inst), | 2241 | .set_union_tag => return self.airSetUnionTag(inst), |
| 2141 | .get_union_tag => try self.airGetUnionTag(inst), | 2242 | .get_union_tag => try self.airGetUnionTag(inst), |
| 2142 | .union_init => try self.airUnionInit(inst), | 2243 | .union_init => try self.airUnionInit(inst), |
| ... | @@ -2189,13 +2290,16 @@ const DeclGen = struct { | ... | @@ -2189,13 +2290,16 @@ const DeclGen = struct { |
| 2189 | .wrap_errunion_err => try self.airWrapErrUnionErr(inst), | 2290 | .wrap_errunion_err => try self.airWrapErrUnionErr(inst), |
| 2190 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 2291 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| 2191 | 2292 | ||
| 2192 | .is_null => try self.airIsNull(inst, .is_null), | 2293 | .is_null => try self.airIsNull(inst, false, .is_null), |
| 2193 | .is_non_null => try self.airIsNull(inst, .is_non_null), | 2294 | .is_non_null => try self.airIsNull(inst, false, .is_non_null), |
| 2194 | .is_err => try self.airIsErr(inst, .is_err), | 2295 | .is_null_ptr => try self.airIsNull(inst, true, .is_null), |
| 2195 | .is_non_err => try self.airIsErr(inst, .is_non_err), | 2296 | .is_non_null_ptr => try self.airIsNull(inst, true, .is_non_null), |
| 2297 | .is_err => try self.airIsErr(inst, .is_err), | ||
| 2298 | .is_non_err => try self.airIsErr(inst, .is_non_err), | ||
| 2196 | 2299 | ||
| 2197 | .optional_payload => try self.airUnwrapOptional(inst), | 2300 | .optional_payload => try self.airUnwrapOptional(inst), |
| 2198 | .wrap_optional => try self.airWrapOptional(inst), | 2301 | .optional_payload_ptr => try self.airUnwrapOptionalPtr(inst), |
| 2302 | .wrap_optional => try self.airWrapOptional(inst), | ||
| 2199 | 2303 | ||
| 2200 | .assembly => try self.airAssembly(inst), | 2304 | .assembly => try self.airAssembly(inst), |
| 2201 | 2305 | ||
| ... | @@ -2213,34 +2317,17 @@ const DeclGen = struct { | ... | @@ -2213,34 +2317,17 @@ const DeclGen = struct { |
| 2213 | } | 2317 | } |
| 2214 | 2318 | ||
| 2215 | fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef { | 2319 | fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef { |
| 2216 | const mod = self.module; | 2320 | var wip = try self.elementWise(ty); |
| 2217 | 2321 | defer wip.deinit(); | |
| 2218 | if (ty.isVector(mod)) { | 2322 | for (0..wip.results.len) |i| { |
| 2219 | const child_ty = ty.childType(mod); | 2323 | try self.func.body.emit(self.spv.gpa, opcode, .{ |
| 2220 | const vector_len = ty.vectorLen(mod); | 2324 | .id_result_type = wip.scalar_ty_id, |
| 2221 | 2325 | .id_result = wip.allocId(i), | |
| 2222 | const constituents = try self.gpa.alloc(IdRef, vector_len); | 2326 | .operand_1 = try wip.elementAt(ty, lhs_id, i), |
| 2223 | defer self.gpa.free(constituents); | 2327 | .operand_2 = try wip.elementAt(ty, rhs_id, i), |
| 2224 | 2328 | }); | |
| 2225 | for (constituents, 0..) |*constituent, i| { | ||
| 2226 | const lhs_index_id = try self.extractField(child_ty, lhs_id, @intCast(i)); | ||
| 2227 | const rhs_index_id = try self.extractField(child_ty, rhs_id, @intCast(i)); | ||
| 2228 | const result_id = try self.binOpSimple(child_ty, lhs_index_id, rhs_index_id, opcode); | ||
| 2229 | constituent.* = try self.convertToIndirect(child_ty, result_id); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | return try self.constructArray(ty, constituents); | ||
| 2233 | } | 2329 | } |
| 2234 | 2330 | return try wip.finalize(); | |
| 2235 | const result_id = self.spv.allocId(); | ||
| 2236 | const result_type_id = try self.resolveTypeId(ty); | ||
| 2237 | try self.func.body.emit(self.spv.gpa, opcode, .{ | ||
| 2238 | .id_result_type = result_type_id, | ||
| 2239 | .id_result = result_id, | ||
| 2240 | .operand_1 = lhs_id, | ||
| 2241 | .operand_2 = rhs_id, | ||
| 2242 | }); | ||
| 2243 | return result_id; | ||
| 2244 | } | 2331 | } |
| 2245 | 2332 | ||
| 2246 | fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { | 2333 | fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { |
| ... | @@ -2254,29 +2341,59 @@ const DeclGen = struct { | ... | @@ -2254,29 +2341,59 @@ const DeclGen = struct { |
| 2254 | return try self.binOpSimple(ty, lhs_id, rhs_id, opcode); | 2341 | return try self.binOpSimple(ty, lhs_id, rhs_id, opcode); |
| 2255 | } | 2342 | } |
| 2256 | 2343 | ||
| 2257 | fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { | 2344 | fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime unsigned: Opcode, comptime signed: Opcode) !?IdRef { |
| 2258 | if (self.liveness.isUnused(inst)) return null; | 2345 | if (self.liveness.isUnused(inst)) return null; |
| 2346 | const mod = self.module; | ||
| 2259 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 2347 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2260 | const lhs_id = try self.resolve(bin_op.lhs); | 2348 | const lhs_id = try self.resolve(bin_op.lhs); |
| 2261 | const rhs_id = try self.resolve(bin_op.rhs); | 2349 | const rhs_id = try self.resolve(bin_op.rhs); |
| 2262 | const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst)); | ||
| 2263 | 2350 | ||
| 2264 | // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int. | 2351 | const result_ty = self.typeOfIndex(inst); |
| 2265 | const shift_id = self.spv.allocId(); | 2352 | const shift_ty = self.typeOf(bin_op.rhs); |
| 2266 | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ | 2353 | const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct); |
| 2267 | .id_result_type = result_type_id, | ||
| 2268 | .id_result = shift_id, | ||
| 2269 | .unsigned_value = rhs_id, | ||
| 2270 | }); | ||
| 2271 | 2354 | ||
| 2272 | const result_id = self.spv.allocId(); | 2355 | const info = self.arithmeticTypeInfo(result_ty); |
| 2273 | try self.func.body.emit(self.spv.gpa, opcode, .{ | 2356 | switch (info.class) { |
| 2274 | .id_result_type = result_type_id, | 2357 | .composite_integer => return self.todo("shift ops for composite integers", .{}), |
| 2275 | .id_result = result_id, | 2358 | .integer, .strange_integer => {}, |
| 2276 | .base = lhs_id, | 2359 | .float, .bool => unreachable, |
| 2277 | .shift = shift_id, | 2360 | } |
| 2278 | }); | 2361 | |
| 2279 | return result_id; | 2362 | var wip = try self.elementWise(result_ty); |
| 2363 | defer wip.deinit(); | ||
| 2364 | for (wip.results, 0..) |*result_id, i| { | ||
| 2365 | const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i); | ||
| 2366 | const rhs_elem_id = try wip.elementAt(shift_ty, rhs_id, i); | ||
| 2367 | |||
| 2368 | // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that, | ||
| 2369 | // so just manually upcast it if required. | ||
| 2370 | const shift_id = if (scalar_shift_ty_ref != wip.scalar_ty_ref) blk: { | ||
| 2371 | const shift_id = self.spv.allocId(); | ||
| 2372 | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ | ||
| 2373 | .id_result_type = wip.scalar_ty_id, | ||
| 2374 | .id_result = shift_id, | ||
| 2375 | .unsigned_value = rhs_elem_id, | ||
| 2376 | }); | ||
| 2377 | break :blk shift_id; | ||
| 2378 | } else rhs_elem_id; | ||
| 2379 | |||
| 2380 | const value_id = self.spv.allocId(); | ||
| 2381 | const args = .{ | ||
| 2382 | .id_result_type = wip.scalar_ty_id, | ||
| 2383 | .id_result = value_id, | ||
| 2384 | .base = lhs_elem_id, | ||
| 2385 | .shift = shift_id, | ||
| 2386 | }; | ||
| 2387 | |||
| 2388 | if (result_ty.isSignedInt(mod)) { | ||
| 2389 | try self.func.body.emit(self.spv.gpa, signed, args); | ||
| 2390 | } else { | ||
| 2391 | try self.func.body.emit(self.spv.gpa, unsigned, args); | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, info); | ||
| 2395 | } | ||
| 2396 | return try wip.finalize(); | ||
| 2280 | } | 2397 | } |
| 2281 | 2398 | ||
| 2282 | fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !?IdRef { | 2399 | fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !?IdRef { |
| ... | @@ -2286,88 +2403,102 @@ const DeclGen = struct { | ... | @@ -2286,88 +2403,102 @@ const DeclGen = struct { |
| 2286 | const lhs_id = try self.resolve(bin_op.lhs); | 2403 | const lhs_id = try self.resolve(bin_op.lhs); |
| 2287 | const rhs_id = try self.resolve(bin_op.rhs); | 2404 | const rhs_id = try self.resolve(bin_op.rhs); |
| 2288 | const result_ty = self.typeOfIndex(inst); | 2405 | const result_ty = self.typeOfIndex(inst); |
| 2289 | const result_ty_ref = try self.resolveType(result_ty, .direct); | ||
| 2290 | |||
| 2291 | const info = try self.arithmeticTypeInfo(result_ty); | ||
| 2292 | // TODO: Use fmin for OpenCL | ||
| 2293 | const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id); | ||
| 2294 | const selection_id = switch (info.class) { | ||
| 2295 | .float => blk: { | ||
| 2296 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, | ||
| 2297 | // but we want it to pick lhs. Therefore we also have to check if | ||
| 2298 | // rhs is nan. We don't need to care about the result when both | ||
| 2299 | // are nan. | ||
| 2300 | const rhs_is_nan_id = self.spv.allocId(); | ||
| 2301 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | ||
| 2302 | try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ | ||
| 2303 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2304 | .id_result = rhs_is_nan_id, | ||
| 2305 | .x = rhs_id, | ||
| 2306 | }); | ||
| 2307 | const float_cmp_id = self.spv.allocId(); | ||
| 2308 | try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ | ||
| 2309 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2310 | .id_result = float_cmp_id, | ||
| 2311 | .operand_1 = cmp_id, | ||
| 2312 | .operand_2 = rhs_is_nan_id, | ||
| 2313 | }); | ||
| 2314 | break :blk float_cmp_id; | ||
| 2315 | }, | ||
| 2316 | else => cmp_id, | ||
| 2317 | }; | ||
| 2318 | 2406 | ||
| 2319 | const result_id = self.spv.allocId(); | 2407 | return try self.minMax(result_ty, op, lhs_id, rhs_id); |
| 2320 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | 2408 | } |
| 2321 | .id_result_type = self.typeId(result_ty_ref), | 2409 | |
| 2322 | .id_result = result_id, | 2410 | fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef { |
| 2323 | .condition = selection_id, | 2411 | const info = self.arithmeticTypeInfo(result_ty); |
| 2324 | .object_1 = lhs_id, | 2412 | |
| 2325 | .object_2 = rhs_id, | 2413 | var wip = try self.elementWise(result_ty); |
| 2326 | }); | 2414 | defer wip.deinit(); |
| 2327 | return result_id; | 2415 | for (wip.results, 0..) |*result_id, i| { |
| 2328 | } | 2416 | const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i); |
| 2417 | const rhs_elem_id = try wip.elementAt(result_ty, rhs_id, i); | ||
| 2418 | |||
| 2419 | // TODO: Use fmin for OpenCL | ||
| 2420 | const cmp_id = try self.cmp(op, Type.bool, wip.scalar_ty, lhs_elem_id, rhs_elem_id); | ||
| 2421 | const selection_id = switch (info.class) { | ||
| 2422 | .float => blk: { | ||
| 2423 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, | ||
| 2424 | // but we want it to pick lhs. Therefore we also have to check if | ||
| 2425 | // rhs is nan. We don't need to care about the result when both | ||
| 2426 | // are nan. | ||
| 2427 | const rhs_is_nan_id = self.spv.allocId(); | ||
| 2428 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | ||
| 2429 | try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ | ||
| 2430 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2431 | .id_result = rhs_is_nan_id, | ||
| 2432 | .x = rhs_elem_id, | ||
| 2433 | }); | ||
| 2434 | const float_cmp_id = self.spv.allocId(); | ||
| 2435 | try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ | ||
| 2436 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2437 | .id_result = float_cmp_id, | ||
| 2438 | .operand_1 = cmp_id, | ||
| 2439 | .operand_2 = rhs_is_nan_id, | ||
| 2440 | }); | ||
| 2441 | break :blk float_cmp_id; | ||
| 2442 | }, | ||
| 2443 | else => cmp_id, | ||
| 2444 | }; | ||
| 2329 | 2445 | ||
| 2330 | /// This function canonicalizes a "strange" integer value: | 2446 | result_id.* = self.spv.allocId(); |
| 2331 | /// For unsigned integers, the value is masked so that only the relevant bits can contain | 2447 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ |
| 2332 | /// non-zeros. | 2448 | .id_result_type = wip.scalar_ty_id, |
| 2333 | /// For signed integers, the value is also sign extended. | 2449 | .id_result = result_id.*, |
| 2334 | fn normalizeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, info: ArithmeticTypeInfo) !IdRef { | 2450 | .condition = selection_id, |
| 2335 | assert(info.class != .composite_integer); // TODO | 2451 | .object_1 = lhs_elem_id, |
| 2336 | if (info.bits == info.backing_bits) { | 2452 | .object_2 = rhs_elem_id, |
| 2337 | return value_id; | 2453 | }); |
| 2338 | } | 2454 | } |
| 2339 | 2455 | return wip.finalize(); | |
| 2340 | switch (info.signedness) { | 2456 | } |
| 2341 | .unsigned => { | 2457 | |
| 2342 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; | 2458 | /// This function normalizes values to a canonical representation |
| 2343 | const result_id = self.spv.allocId(); | 2459 | /// after some arithmetic operation. This mostly consists of wrapping |
| 2344 | const mask_id = try self.constInt(ty_ref, mask_value); | 2460 | /// behavior for strange integers: |
| 2345 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ | 2461 | /// - Unsigned integers are bitwise masked with a mask that only passes |
| 2346 | .id_result_type = self.typeId(ty_ref), | 2462 | /// the valid bits through. |
| 2347 | .id_result = result_id, | 2463 | /// - Signed integers are also sign extended if they are negative. |
| 2348 | .operand_1 = value_id, | 2464 | /// All other values are returned unmodified (this makes strange integer |
| 2349 | .operand_2 = mask_id, | 2465 | /// wrapping easier to use in generic operations). |
| 2350 | }); | 2466 | fn normalize(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, info: ArithmeticTypeInfo) !IdRef { |
| 2351 | return result_id; | 2467 | switch (info.class) { |
| 2352 | }, | 2468 | .integer, .bool, .float => return value_id, |
| 2353 | .signed => { | 2469 | .composite_integer => unreachable, // TODO |
| 2354 | // Shift left and right so that we can copy the sight bit that way. | 2470 | .strange_integer => switch (info.signedness) { |
| 2355 | const shift_amt_id = try self.constInt(ty_ref, info.backing_bits - info.bits); | 2471 | .unsigned => { |
| 2356 | const left_id = self.spv.allocId(); | 2472 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; |
| 2357 | try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ | 2473 | const result_id = self.spv.allocId(); |
| 2358 | .id_result_type = self.typeId(ty_ref), | 2474 | const mask_id = try self.constInt(ty_ref, mask_value); |
| 2359 | .id_result = left_id, | 2475 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ |
| 2360 | .base = value_id, | 2476 | .id_result_type = self.typeId(ty_ref), |
| 2361 | .shift = shift_amt_id, | 2477 | .id_result = result_id, |
| 2362 | }); | 2478 | .operand_1 = value_id, |
| 2363 | const right_id = self.spv.allocId(); | 2479 | .operand_2 = mask_id, |
| 2364 | try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ | 2480 | }); |
| 2365 | .id_result_type = self.typeId(ty_ref), | 2481 | return result_id; |
| 2366 | .id_result = right_id, | 2482 | }, |
| 2367 | .base = left_id, | 2483 | .signed => { |
| 2368 | .shift = shift_amt_id, | 2484 | // Shift left and right so that we can copy the sight bit that way. |
| 2369 | }); | 2485 | const shift_amt_id = try self.constInt(ty_ref, info.backing_bits - info.bits); |
| 2370 | return right_id; | 2486 | const left_id = self.spv.allocId(); |
| 2487 | try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ | ||
| 2488 | .id_result_type = self.typeId(ty_ref), | ||
| 2489 | .id_result = left_id, | ||
| 2490 | .base = value_id, | ||
| 2491 | .shift = shift_amt_id, | ||
| 2492 | }); | ||
| 2493 | const right_id = self.spv.allocId(); | ||
| 2494 | try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ | ||
| 2495 | .id_result_type = self.typeId(ty_ref), | ||
| 2496 | .id_result = right_id, | ||
| 2497 | .base = left_id, | ||
| 2498 | .shift = shift_amt_id, | ||
| 2499 | }); | ||
| 2500 | return right_id; | ||
| 2501 | }, | ||
| 2371 | }, | 2502 | }, |
| 2372 | } | 2503 | } |
| 2373 | } | 2504 | } |
| ... | @@ -2378,8 +2509,6 @@ const DeclGen = struct { | ... | @@ -2378,8 +2509,6 @@ const DeclGen = struct { |
| 2378 | comptime fop: Opcode, | 2509 | comptime fop: Opcode, |
| 2379 | comptime sop: Opcode, | 2510 | comptime sop: Opcode, |
| 2380 | comptime uop: Opcode, | 2511 | comptime uop: Opcode, |
| 2381 | /// true if this operation holds under modular arithmetic. | ||
| 2382 | comptime modular: bool, | ||
| 2383 | ) !?IdRef { | 2512 | ) !?IdRef { |
| 2384 | if (self.liveness.isUnused(inst)) return null; | 2513 | if (self.liveness.isUnused(inst)) return null; |
| 2385 | 2514 | ||
| ... | @@ -2393,60 +2522,27 @@ const DeclGen = struct { | ... | @@ -2393,60 +2522,27 @@ const DeclGen = struct { |
| 2393 | assert(self.typeOf(bin_op.lhs).eql(ty, self.module)); | 2522 | assert(self.typeOf(bin_op.lhs).eql(ty, self.module)); |
| 2394 | assert(self.typeOf(bin_op.rhs).eql(ty, self.module)); | 2523 | assert(self.typeOf(bin_op.rhs).eql(ty, self.module)); |
| 2395 | 2524 | ||
| 2396 | return try self.arithOp(ty, lhs_id, rhs_id, fop, sop, uop, modular); | 2525 | return try self.arithOp(ty, lhs_id, rhs_id, fop, sop, uop); |
| 2397 | } | 2526 | } |
| 2398 | 2527 | ||
| 2399 | fn arithOp( | 2528 | fn arithOp( |
| 2400 | self: *DeclGen, | 2529 | self: *DeclGen, |
| 2401 | ty: Type, | 2530 | ty: Type, |
| 2402 | lhs_id_: IdRef, | 2531 | lhs_id: IdRef, |
| 2403 | rhs_id_: IdRef, | 2532 | rhs_id: IdRef, |
| 2404 | comptime fop: Opcode, | 2533 | comptime fop: Opcode, |
| 2405 | comptime sop: Opcode, | 2534 | comptime sop: Opcode, |
| 2406 | comptime uop: Opcode, | 2535 | comptime uop: Opcode, |
| 2407 | /// true if this operation holds under modular arithmetic. | ||
| 2408 | comptime modular: bool, | ||
| 2409 | ) !IdRef { | 2536 | ) !IdRef { |
| 2410 | var rhs_id = rhs_id_; | ||
| 2411 | var lhs_id = lhs_id_; | ||
| 2412 | |||
| 2413 | const mod = self.module; | ||
| 2414 | const result_ty_ref = try self.resolveType(ty, .direct); | ||
| 2415 | |||
| 2416 | if (ty.isVector(mod)) { | ||
| 2417 | const child_ty = ty.childType(mod); | ||
| 2418 | const vector_len = ty.vectorLen(mod); | ||
| 2419 | const constituents = try self.gpa.alloc(IdRef, vector_len); | ||
| 2420 | defer self.gpa.free(constituents); | ||
| 2421 | |||
| 2422 | for (constituents, 0..) |*constituent, i| { | ||
| 2423 | const lhs_index_id = try self.extractField(child_ty, lhs_id, @intCast(i)); | ||
| 2424 | const rhs_index_id = try self.extractField(child_ty, rhs_id, @intCast(i)); | ||
| 2425 | constituent.* = try self.arithOp(child_ty, lhs_index_id, rhs_index_id, fop, sop, uop, modular); | ||
| 2426 | } | ||
| 2427 | |||
| 2428 | return self.constructArray(ty, constituents); | ||
| 2429 | } | ||
| 2430 | |||
| 2431 | // Binary operations are generally applicable to both scalar and vector operations | 2537 | // Binary operations are generally applicable to both scalar and vector operations |
| 2432 | // in SPIR-V, but int and float versions of operations require different opcodes. | 2538 | // in SPIR-V, but int and float versions of operations require different opcodes. |
| 2433 | const info = try self.arithmeticTypeInfo(ty); | 2539 | const info = self.arithmeticTypeInfo(ty); |
| 2434 | 2540 | ||
| 2435 | const opcode_index: usize = switch (info.class) { | 2541 | const opcode_index: usize = switch (info.class) { |
| 2436 | .composite_integer => { | 2542 | .composite_integer => { |
| 2437 | return self.todo("binary operations for composite integers", .{}); | 2543 | return self.todo("binary operations for composite integers", .{}); |
| 2438 | }, | 2544 | }, |
| 2439 | .strange_integer => blk: { | 2545 | .integer, .strange_integer => switch (info.signedness) { |
| 2440 | if (!modular) { | ||
| 2441 | lhs_id = try self.normalizeInt(result_ty_ref, lhs_id, info); | ||
| 2442 | rhs_id = try self.normalizeInt(result_ty_ref, rhs_id, info); | ||
| 2443 | } | ||
| 2444 | break :blk switch (info.signedness) { | ||
| 2445 | .signed => @as(usize, 1), | ||
| 2446 | .unsigned => @as(usize, 2), | ||
| 2447 | }; | ||
| 2448 | }, | ||
| 2449 | .integer => switch (info.signedness) { | ||
| 2450 | .signed => @as(usize, 1), | 2546 | .signed => @as(usize, 1), |
| 2451 | .unsigned => @as(usize, 2), | 2547 | .unsigned => @as(usize, 2), |
| 2452 | }, | 2548 | }, |
| ... | @@ -2454,24 +2550,91 @@ const DeclGen = struct { | ... | @@ -2454,24 +2550,91 @@ const DeclGen = struct { |
| 2454 | .bool => unreachable, | 2550 | .bool => unreachable, |
| 2455 | }; | 2551 | }; |
| 2456 | 2552 | ||
| 2457 | const result_id = self.spv.allocId(); | 2553 | var wip = try self.elementWise(ty); |
| 2458 | const operands = .{ | 2554 | defer wip.deinit(); |
| 2459 | .id_result_type = self.typeId(result_ty_ref), | 2555 | for (wip.results, 0..) |*result_id, i| { |
| 2460 | .id_result = result_id, | 2556 | const lhs_elem_id = try wip.elementAt(ty, lhs_id, i); |
| 2461 | .operand_1 = lhs_id, | 2557 | const rhs_elem_id = try wip.elementAt(ty, rhs_id, i); |
| 2462 | .operand_2 = rhs_id, | 2558 | |
| 2463 | }; | 2559 | const value_id = self.spv.allocId(); |
| 2560 | const operands = .{ | ||
| 2561 | .id_result_type = wip.scalar_ty_id, | ||
| 2562 | .id_result = value_id, | ||
| 2563 | .operand_1 = lhs_elem_id, | ||
| 2564 | .operand_2 = rhs_elem_id, | ||
| 2565 | }; | ||
| 2464 | 2566 | ||
| 2465 | switch (opcode_index) { | 2567 | switch (opcode_index) { |
| 2466 | 0 => try self.func.body.emit(self.spv.gpa, fop, operands), | 2568 | 0 => try self.func.body.emit(self.spv.gpa, fop, operands), |
| 2467 | 1 => try self.func.body.emit(self.spv.gpa, sop, operands), | 2569 | 1 => try self.func.body.emit(self.spv.gpa, sop, operands), |
| 2468 | 2 => try self.func.body.emit(self.spv.gpa, uop, operands), | 2570 | 2 => try self.func.body.emit(self.spv.gpa, uop, operands), |
| 2469 | else => unreachable, | 2571 | else => unreachable, |
| 2572 | } | ||
| 2573 | |||
| 2574 | // TODO: Trap on overflow? Probably going to be annoying. | ||
| 2575 | // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap. | ||
| 2576 | result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, info); | ||
| 2470 | } | 2577 | } |
| 2471 | // TODO: Trap on overflow? Probably going to be annoying. | ||
| 2472 | // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap. | ||
| 2473 | 2578 | ||
| 2474 | return result_id; | 2579 | return try wip.finalize(); |
| 2580 | } | ||
| 2581 | |||
| 2582 | fn airAbs(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2583 | if (self.liveness.isUnused(inst)) return null; | ||
| 2584 | |||
| 2585 | const mod = self.module; | ||
| 2586 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | ||
| 2587 | const operand_id = try self.resolve(ty_op.operand); | ||
| 2588 | // Note: operand_ty may be signed, while ty is always unsigned! | ||
| 2589 | const operand_ty = self.typeOf(ty_op.operand); | ||
| 2590 | const ty = self.typeOfIndex(inst); | ||
| 2591 | const info = self.arithmeticTypeInfo(ty); | ||
| 2592 | const operand_scalar_ty = operand_ty.scalarType(mod); | ||
| 2593 | const operand_scalar_ty_ref = try self.resolveType(operand_scalar_ty, .direct); | ||
| 2594 | |||
| 2595 | var wip = try self.elementWise(ty); | ||
| 2596 | defer wip.deinit(); | ||
| 2597 | |||
| 2598 | const zero_id = switch (info.class) { | ||
| 2599 | .float => try self.constFloat(operand_scalar_ty_ref, 0), | ||
| 2600 | .integer, .strange_integer => try self.constInt(operand_scalar_ty_ref, 0), | ||
| 2601 | .composite_integer => unreachable, // TODO | ||
| 2602 | .bool => unreachable, | ||
| 2603 | }; | ||
| 2604 | for (wip.results, 0..) |*result_id, i| { | ||
| 2605 | const elem_id = try wip.elementAt(operand_ty, operand_id, i); | ||
| 2606 | // Idk why spir-v doesn't have a dedicated abs() instruction in the base | ||
| 2607 | // instruction set. For now we're just going to negate and check to avoid | ||
| 2608 | // importing the extinst. | ||
| 2609 | // TODO: Make this a call to compiler rt / ext inst | ||
| 2610 | const neg_id = self.spv.allocId(); | ||
| 2611 | const args = .{ | ||
| 2612 | .id_result_type = self.typeId(operand_scalar_ty_ref), | ||
| 2613 | .id_result = neg_id, | ||
| 2614 | .operand_1 = zero_id, | ||
| 2615 | .operand_2 = elem_id, | ||
| 2616 | }; | ||
| 2617 | switch (info.class) { | ||
| 2618 | .float => try self.func.body.emit(self.spv.gpa, .OpFSub, args), | ||
| 2619 | .integer, .strange_integer => try self.func.body.emit(self.spv.gpa, .OpISub, args), | ||
| 2620 | .composite_integer => unreachable, // TODO | ||
| 2621 | .bool => unreachable, | ||
| 2622 | } | ||
| 2623 | const neg_norm_id = try self.normalize(wip.scalar_ty_ref, neg_id, info); | ||
| 2624 | |||
| 2625 | const gt_zero_id = try self.cmp(.gt, Type.bool, operand_scalar_ty, elem_id, zero_id); | ||
| 2626 | const abs_id = self.spv.allocId(); | ||
| 2627 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | ||
| 2628 | .id_result_type = self.typeId(operand_scalar_ty_ref), | ||
| 2629 | .id_result = abs_id, | ||
| 2630 | .condition = gt_zero_id, | ||
| 2631 | .object_1 = elem_id, | ||
| 2632 | .object_2 = neg_norm_id, | ||
| 2633 | }); | ||
| 2634 | // For Shader, we may need to cast from signed to unsigned here. | ||
| 2635 | result_id.* = try self.bitCast(wip.scalar_ty, operand_scalar_ty, abs_id); | ||
| 2636 | } | ||
| 2637 | return try wip.finalize(); | ||
| 2475 | } | 2638 | } |
| 2476 | 2639 | ||
| 2477 | fn airAddSubOverflow( | 2640 | fn airAddSubOverflow( |
| ... | @@ -2488,140 +2651,344 @@ const DeclGen = struct { | ... | @@ -2488,140 +2651,344 @@ const DeclGen = struct { |
| 2488 | const lhs = try self.resolve(extra.lhs); | 2651 | const lhs = try self.resolve(extra.lhs); |
| 2489 | const rhs = try self.resolve(extra.rhs); | 2652 | const rhs = try self.resolve(extra.rhs); |
| 2490 | 2653 | ||
| 2491 | const operand_ty = self.typeOf(extra.lhs); | ||
| 2492 | const result_ty = self.typeOfIndex(inst); | 2654 | const result_ty = self.typeOfIndex(inst); |
| 2655 | const operand_ty = self.typeOf(extra.lhs); | ||
| 2656 | const ov_ty = result_ty.structFieldType(1, self.module); | ||
| 2657 | |||
| 2658 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | ||
| 2493 | 2659 | ||
| 2494 | const info = try self.arithmeticTypeInfo(operand_ty); | 2660 | const info = self.arithmeticTypeInfo(operand_ty); |
| 2495 | switch (info.class) { | 2661 | switch (info.class) { |
| 2496 | .composite_integer => return self.todo("overflow ops for composite integers", .{}), | 2662 | .composite_integer => return self.todo("overflow ops for composite integers", .{}), |
| 2497 | .strange_integer => return self.todo("overflow ops for strange integers", .{}), | 2663 | .strange_integer, .integer => {}, |
| 2498 | .integer => {}, | ||
| 2499 | .float, .bool => unreachable, | 2664 | .float, .bool => unreachable, |
| 2500 | } | 2665 | } |
| 2501 | 2666 | ||
| 2502 | // The operand type must be the same as the result type in SPIR-V, which | 2667 | var wip_result = try self.elementWise(operand_ty); |
| 2503 | // is the same as in Zig. | 2668 | defer wip_result.deinit(); |
| 2504 | const operand_ty_ref = try self.resolveType(operand_ty, .direct); | 2669 | var wip_ov = try self.elementWise(ov_ty); |
| 2505 | const operand_ty_id = self.typeId(operand_ty_ref); | 2670 | defer wip_ov.deinit(); |
| 2671 | for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| { | ||
| 2672 | const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i); | ||
| 2673 | const rhs_elem_id = try wip_result.elementAt(operand_ty, rhs, i); | ||
| 2674 | |||
| 2675 | // Normalize both so that we can properly check for overflow | ||
| 2676 | const value_id = self.spv.allocId(); | ||
| 2677 | |||
| 2678 | try self.func.body.emit(self.spv.gpa, add, .{ | ||
| 2679 | .id_result_type = wip_result.scalar_ty_id, | ||
| 2680 | .id_result = value_id, | ||
| 2681 | .operand_1 = lhs_elem_id, | ||
| 2682 | .operand_2 = rhs_elem_id, | ||
| 2683 | }); | ||
| 2506 | 2684 | ||
| 2507 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 2685 | // Normalize the result so that the comparisons go well |
| 2686 | result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info); | ||
| 2687 | |||
| 2688 | const overflowed_id = switch (info.signedness) { | ||
| 2689 | .unsigned => blk: { | ||
| 2690 | // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. | ||
| 2691 | // For subtraction the conditions need to be swapped. | ||
| 2692 | const overflowed_id = self.spv.allocId(); | ||
| 2693 | try self.func.body.emit(self.spv.gpa, ucmp, .{ | ||
| 2694 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2695 | .id_result = overflowed_id, | ||
| 2696 | .operand_1 = result_id.*, | ||
| 2697 | .operand_2 = lhs_elem_id, | ||
| 2698 | }); | ||
| 2699 | break :blk overflowed_id; | ||
| 2700 | }, | ||
| 2701 | .signed => blk: { | ||
| 2702 | // lhs - rhs | ||
| 2703 | // For addition, overflow happened if: | ||
| 2704 | // - rhs is negative and value > lhs | ||
| 2705 | // - rhs is positive and value < lhs | ||
| 2706 | // This can be shortened to: | ||
| 2707 | // (rhs < 0 and value > lhs) or (rhs >= 0 and value <= lhs) | ||
| 2708 | // = (rhs < 0) == (value > lhs) | ||
| 2709 | // = (rhs < 0) == (lhs < value) | ||
| 2710 | // Note that signed overflow is also wrapping in spir-v. | ||
| 2711 | // For subtraction, overflow happened if: | ||
| 2712 | // - rhs is negative and value < lhs | ||
| 2713 | // - rhs is positive and value > lhs | ||
| 2714 | // This can be shortened to: | ||
| 2715 | // (rhs < 0 and value < lhs) or (rhs >= 0 and value >= lhs) | ||
| 2716 | // = (rhs < 0) == (value < lhs) | ||
| 2717 | // = (rhs < 0) == (lhs > value) | ||
| 2718 | |||
| 2719 | const rhs_lt_zero_id = self.spv.allocId(); | ||
| 2720 | const zero_id = try self.constInt(wip_result.scalar_ty_ref, 0); | ||
| 2721 | try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ | ||
| 2722 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2723 | .id_result = rhs_lt_zero_id, | ||
| 2724 | .operand_1 = rhs_elem_id, | ||
| 2725 | .operand_2 = zero_id, | ||
| 2726 | }); | ||
| 2727 | |||
| 2728 | const value_gt_lhs_id = self.spv.allocId(); | ||
| 2729 | try self.func.body.emit(self.spv.gpa, scmp, .{ | ||
| 2730 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2731 | .id_result = value_gt_lhs_id, | ||
| 2732 | .operand_1 = lhs_elem_id, | ||
| 2733 | .operand_2 = result_id.*, | ||
| 2734 | }); | ||
| 2735 | |||
| 2736 | const overflowed_id = self.spv.allocId(); | ||
| 2737 | try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{ | ||
| 2738 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2739 | .id_result = overflowed_id, | ||
| 2740 | .operand_1 = rhs_lt_zero_id, | ||
| 2741 | .operand_2 = value_gt_lhs_id, | ||
| 2742 | }); | ||
| 2743 | break :blk overflowed_id; | ||
| 2744 | }, | ||
| 2745 | }; | ||
| 2746 | |||
| 2747 | ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id); | ||
| 2748 | } | ||
| 2749 | |||
| 2750 | return try self.constructStruct( | ||
| 2751 | result_ty, | ||
| 2752 | &.{ operand_ty, ov_ty }, | ||
| 2753 | &.{ try wip_result.finalize(), try wip_ov.finalize() }, | ||
| 2754 | ); | ||
| 2755 | } | ||
| 2756 | |||
| 2757 | fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2758 | if (self.liveness.isUnused(inst)) return null; | ||
| 2759 | const mod = self.module; | ||
| 2760 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 2761 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 2762 | const lhs = try self.resolve(extra.lhs); | ||
| 2763 | const rhs = try self.resolve(extra.rhs); | ||
| 2764 | |||
| 2765 | const result_ty = self.typeOfIndex(inst); | ||
| 2766 | const operand_ty = self.typeOf(extra.lhs); | ||
| 2767 | const shift_ty = self.typeOf(extra.rhs); | ||
| 2768 | const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct); | ||
| 2508 | 2769 | ||
| 2509 | const ov_ty = result_ty.structFieldType(1, self.module); | 2770 | const ov_ty = result_ty.structFieldType(1, self.module); |
| 2510 | // Note: result is stored in a struct, so indirect representation. | ||
| 2511 | const ov_ty_ref = try self.resolveType(ov_ty, .indirect); | ||
| 2512 | |||
| 2513 | // TODO: Operations other than addition. | ||
| 2514 | const value_id = self.spv.allocId(); | ||
| 2515 | try self.func.body.emit(self.spv.gpa, add, .{ | ||
| 2516 | .id_result_type = operand_ty_id, | ||
| 2517 | .id_result = value_id, | ||
| 2518 | .operand_1 = lhs, | ||
| 2519 | .operand_2 = rhs, | ||
| 2520 | }); | ||
| 2521 | 2771 | ||
| 2522 | const overflowed_id = switch (info.signedness) { | 2772 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2523 | .unsigned => blk: { | ||
| 2524 | // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. | ||
| 2525 | // For subtraction the conditions need to be swapped. | ||
| 2526 | const overflowed_id = self.spv.allocId(); | ||
| 2527 | try self.func.body.emit(self.spv.gpa, ucmp, .{ | ||
| 2528 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2529 | .id_result = overflowed_id, | ||
| 2530 | .operand_1 = value_id, | ||
| 2531 | .operand_2 = lhs, | ||
| 2532 | }); | ||
| 2533 | break :blk overflowed_id; | ||
| 2534 | }, | ||
| 2535 | .signed => blk: { | ||
| 2536 | // lhs - rhs | ||
| 2537 | // For addition, overflow happened if: | ||
| 2538 | // - rhs is negative and value > lhs | ||
| 2539 | // - rhs is positive and value < lhs | ||
| 2540 | // This can be shortened to: | ||
| 2541 | // (rhs < 0 and value > lhs) or (rhs >= 0 and value <= lhs) | ||
| 2542 | // = (rhs < 0) == (value > lhs) | ||
| 2543 | // = (rhs < 0) == (lhs < value) | ||
| 2544 | // Note that signed overflow is also wrapping in spir-v. | ||
| 2545 | // For subtraction, overflow happened if: | ||
| 2546 | // - rhs is negative and value < lhs | ||
| 2547 | // - rhs is positive and value > lhs | ||
| 2548 | // This can be shortened to: | ||
| 2549 | // (rhs < 0 and value < lhs) or (rhs >= 0 and value >= lhs) | ||
| 2550 | // = (rhs < 0) == (value < lhs) | ||
| 2551 | // = (rhs < 0) == (lhs > value) | ||
| 2552 | |||
| 2553 | const rhs_lt_zero_id = self.spv.allocId(); | ||
| 2554 | const zero_id = try self.constInt(operand_ty_ref, 0); | ||
| 2555 | try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ | ||
| 2556 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2557 | .id_result = rhs_lt_zero_id, | ||
| 2558 | .operand_1 = rhs, | ||
| 2559 | .operand_2 = zero_id, | ||
| 2560 | }); | ||
| 2561 | 2773 | ||
| 2562 | const value_gt_lhs_id = self.spv.allocId(); | 2774 | const info = self.arithmeticTypeInfo(operand_ty); |
| 2563 | try self.func.body.emit(self.spv.gpa, scmp, .{ | 2775 | switch (info.class) { |
| 2564 | .id_result_type = self.typeId(bool_ty_ref), | 2776 | .composite_integer => return self.todo("overflow shift for composite integers", .{}), |
| 2565 | .id_result = value_gt_lhs_id, | 2777 | .integer, .strange_integer => {}, |
| 2566 | .operand_1 = lhs, | 2778 | .float, .bool => unreachable, |
| 2567 | .operand_2 = value_id, | 2779 | } |
| 2568 | }); | ||
| 2569 | 2780 | ||
| 2570 | const overflowed_id = self.spv.allocId(); | 2781 | var wip_result = try self.elementWise(operand_ty); |
| 2571 | try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{ | 2782 | defer wip_result.deinit(); |
| 2572 | .id_result_type = self.typeId(bool_ty_ref), | 2783 | var wip_ov = try self.elementWise(ov_ty); |
| 2573 | .id_result = overflowed_id, | 2784 | defer wip_ov.deinit(); |
| 2574 | .operand_1 = rhs_lt_zero_id, | 2785 | for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| { |
| 2575 | .operand_2 = value_gt_lhs_id, | 2786 | const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i); |
| 2787 | const rhs_elem_id = try wip_result.elementAt(shift_ty, rhs, i); | ||
| 2788 | |||
| 2789 | // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that, | ||
| 2790 | // so just manually upcast it if required. | ||
| 2791 | const shift_id = if (scalar_shift_ty_ref != wip_result.scalar_ty_ref) blk: { | ||
| 2792 | const shift_id = self.spv.allocId(); | ||
| 2793 | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ | ||
| 2794 | .id_result_type = wip_result.scalar_ty_id, | ||
| 2795 | .id_result = shift_id, | ||
| 2796 | .unsigned_value = rhs_elem_id, | ||
| 2576 | }); | 2797 | }); |
| 2577 | break :blk overflowed_id; | 2798 | break :blk shift_id; |
| 2578 | }, | 2799 | } else rhs_elem_id; |
| 2579 | }; | 2800 | |
| 2801 | const value_id = self.spv.allocId(); | ||
| 2802 | try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ | ||
| 2803 | .id_result_type = wip_result.scalar_ty_id, | ||
| 2804 | .id_result = value_id, | ||
| 2805 | .base = lhs_elem_id, | ||
| 2806 | .shift = shift_id, | ||
| 2807 | }); | ||
| 2808 | result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info); | ||
| 2809 | |||
| 2810 | const right_shift_id = self.spv.allocId(); | ||
| 2811 | switch (info.signedness) { | ||
| 2812 | .signed => { | ||
| 2813 | try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ | ||
| 2814 | .id_result_type = wip_result.scalar_ty_id, | ||
| 2815 | .id_result = right_shift_id, | ||
| 2816 | .base = result_id.*, | ||
| 2817 | .shift = shift_id, | ||
| 2818 | }); | ||
| 2819 | }, | ||
| 2820 | .unsigned => { | ||
| 2821 | try self.func.body.emit(self.spv.gpa, .OpShiftRightLogical, .{ | ||
| 2822 | .id_result_type = wip_result.scalar_ty_id, | ||
| 2823 | .id_result = right_shift_id, | ||
| 2824 | .base = result_id.*, | ||
| 2825 | .shift = shift_id, | ||
| 2826 | }); | ||
| 2827 | }, | ||
| 2828 | } | ||
| 2829 | |||
| 2830 | const overflowed_id = self.spv.allocId(); | ||
| 2831 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ | ||
| 2832 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2833 | .id_result = overflowed_id, | ||
| 2834 | .operand_1 = lhs_elem_id, | ||
| 2835 | .operand_2 = right_shift_id, | ||
| 2836 | }); | ||
| 2837 | |||
| 2838 | ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id); | ||
| 2839 | } | ||
| 2580 | 2840 | ||
| 2581 | // Construct the struct that Zig wants as result. | ||
| 2582 | // The value should already be the correct type. | ||
| 2583 | const ov_id = try self.intFromBool(ov_ty_ref, overflowed_id); | ||
| 2584 | return try self.constructStruct( | 2841 | return try self.constructStruct( |
| 2585 | result_ty, | 2842 | result_ty, |
| 2586 | &.{ operand_ty, ov_ty }, | 2843 | &.{ operand_ty, ov_ty }, |
| 2587 | &.{ value_id, ov_id }, | 2844 | &.{ try wip_result.finalize(), try wip_ov.finalize() }, |
| 2588 | ); | 2845 | ); |
| 2589 | } | 2846 | } |
| 2590 | 2847 | ||
| 2848 | fn airMulAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2849 | if (self.liveness.isUnused(inst)) return null; | ||
| 2850 | |||
| 2851 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 2852 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; | ||
| 2853 | |||
| 2854 | const mulend1 = try self.resolve(extra.lhs); | ||
| 2855 | const mulend2 = try self.resolve(extra.rhs); | ||
| 2856 | const addend = try self.resolve(pl_op.operand); | ||
| 2857 | |||
| 2858 | const ty = self.typeOfIndex(inst); | ||
| 2859 | |||
| 2860 | const info = self.arithmeticTypeInfo(ty); | ||
| 2861 | assert(info.class == .float); // .mul_add is only emitted for floats | ||
| 2862 | |||
| 2863 | var wip = try self.elementWise(ty); | ||
| 2864 | defer wip.deinit(); | ||
| 2865 | for (0..wip.results.len) |i| { | ||
| 2866 | const mul_result = self.spv.allocId(); | ||
| 2867 | try self.func.body.emit(self.spv.gpa, .OpFMul, .{ | ||
| 2868 | .id_result_type = wip.scalar_ty_id, | ||
| 2869 | .id_result = mul_result, | ||
| 2870 | .operand_1 = try wip.elementAt(ty, mulend1, i), | ||
| 2871 | .operand_2 = try wip.elementAt(ty, mulend2, i), | ||
| 2872 | }); | ||
| 2873 | |||
| 2874 | try self.func.body.emit(self.spv.gpa, .OpFAdd, .{ | ||
| 2875 | .id_result_type = wip.scalar_ty_id, | ||
| 2876 | .id_result = wip.allocId(i), | ||
| 2877 | .operand_1 = mul_result, | ||
| 2878 | .operand_2 = try wip.elementAt(ty, addend, i), | ||
| 2879 | }); | ||
| 2880 | } | ||
| 2881 | return try wip.finalize(); | ||
| 2882 | } | ||
| 2883 | |||
| 2884 | fn airSplat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2885 | if (self.liveness.isUnused(inst)) return null; | ||
| 2886 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | ||
| 2887 | const operand_id = try self.resolve(ty_op.operand); | ||
| 2888 | const result_ty = self.typeOfIndex(inst); | ||
| 2889 | var wip = try self.elementWise(result_ty); | ||
| 2890 | defer wip.deinit(); | ||
| 2891 | for (wip.results) |*result_id| { | ||
| 2892 | result_id.* = operand_id; | ||
| 2893 | } | ||
| 2894 | return try wip.finalize(); | ||
| 2895 | } | ||
| 2896 | |||
| 2897 | fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 2898 | if (self.liveness.isUnused(inst)) return null; | ||
| 2899 | const mod = self.module; | ||
| 2900 | const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; | ||
| 2901 | const operand = try self.resolve(reduce.operand); | ||
| 2902 | const operand_ty = self.typeOf(reduce.operand); | ||
| 2903 | const scalar_ty = operand_ty.scalarType(mod); | ||
| 2904 | const scalar_ty_ref = try self.resolveType(scalar_ty, .direct); | ||
| 2905 | const scalar_ty_id = self.typeId(scalar_ty_ref); | ||
| 2906 | |||
| 2907 | const info = self.arithmeticTypeInfo(operand_ty); | ||
| 2908 | |||
| 2909 | var result_id = try self.extractField(scalar_ty, operand, 0); | ||
| 2910 | const len = operand_ty.vectorLen(mod); | ||
| 2911 | |||
| 2912 | switch (reduce.operation) { | ||
| 2913 | .Min, .Max => |op| { | ||
| 2914 | const cmp_op: std.math.CompareOperator = if (op == .Max) .gt else .lt; | ||
| 2915 | for (1..len) |i| { | ||
| 2916 | const lhs = result_id; | ||
| 2917 | const rhs = try self.extractField(scalar_ty, operand, @intCast(i)); | ||
| 2918 | result_id = try self.minMax(scalar_ty, cmp_op, lhs, rhs); | ||
| 2919 | } | ||
| 2920 | |||
| 2921 | return result_id; | ||
| 2922 | }, | ||
| 2923 | else => {}, | ||
| 2924 | } | ||
| 2925 | |||
| 2926 | const opcode: Opcode = switch (info.class) { | ||
| 2927 | .bool => switch (reduce.operation) { | ||
| 2928 | .And => .OpLogicalAnd, | ||
| 2929 | .Or => .OpLogicalOr, | ||
| 2930 | .Xor => .OpLogicalNotEqual, | ||
| 2931 | else => unreachable, | ||
| 2932 | }, | ||
| 2933 | .strange_integer, .integer => switch (reduce.operation) { | ||
| 2934 | .And => .OpBitwiseAnd, | ||
| 2935 | .Or => .OpBitwiseOr, | ||
| 2936 | .Xor => .OpBitwiseXor, | ||
| 2937 | .Add => .OpIAdd, | ||
| 2938 | .Mul => .OpIMul, | ||
| 2939 | else => unreachable, | ||
| 2940 | }, | ||
| 2941 | .float => switch (reduce.operation) { | ||
| 2942 | .Add => .OpFAdd, | ||
| 2943 | .Mul => .OpFMul, | ||
| 2944 | else => unreachable, | ||
| 2945 | }, | ||
| 2946 | .composite_integer => unreachable, // TODO | ||
| 2947 | }; | ||
| 2948 | |||
| 2949 | for (1..len) |i| { | ||
| 2950 | const lhs = result_id; | ||
| 2951 | const rhs = try self.extractField(scalar_ty, operand, @intCast(i)); | ||
| 2952 | result_id = self.spv.allocId(); | ||
| 2953 | |||
| 2954 | try self.func.body.emitRaw(self.spv.gpa, opcode, 4); | ||
| 2955 | self.func.body.writeOperand(spec.IdResultType, scalar_ty_id); | ||
| 2956 | self.func.body.writeOperand(spec.IdResult, result_id); | ||
| 2957 | self.func.body.writeOperand(spec.IdResultType, lhs); | ||
| 2958 | self.func.body.writeOperand(spec.IdResultType, rhs); | ||
| 2959 | } | ||
| 2960 | |||
| 2961 | return result_id; | ||
| 2962 | } | ||
| 2963 | |||
| 2591 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2964 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2592 | const mod = self.module; | 2965 | const mod = self.module; |
| 2593 | if (self.liveness.isUnused(inst)) return null; | 2966 | if (self.liveness.isUnused(inst)) return null; |
| 2594 | const ty = self.typeOfIndex(inst); | ||
| 2595 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 2967 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 2596 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | 2968 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 2597 | const a = try self.resolve(extra.a); | 2969 | const a = try self.resolve(extra.a); |
| 2598 | const b = try self.resolve(extra.b); | 2970 | const b = try self.resolve(extra.b); |
| 2599 | const mask = Value.fromInterned(extra.mask); | 2971 | const mask = Value.fromInterned(extra.mask); |
| 2600 | const mask_len = extra.mask_len; | ||
| 2601 | const a_len = self.typeOf(extra.a).vectorLen(mod); | ||
| 2602 | 2972 | ||
| 2603 | const result_id = self.spv.allocId(); | 2973 | const ty = self.typeOfIndex(inst); |
| 2604 | const result_type_id = try self.resolveTypeId(ty); | ||
| 2605 | // Similar to LLVM, SPIR-V uses indices larger than the length of the first vector | ||
| 2606 | // to index into the second vector. | ||
| 2607 | try self.func.body.emitRaw(self.spv.gpa, .OpVectorShuffle, 4 + mask_len); | ||
| 2608 | self.func.body.writeOperand(spec.IdResultType, result_type_id); | ||
| 2609 | self.func.body.writeOperand(spec.IdResult, result_id); | ||
| 2610 | self.func.body.writeOperand(spec.IdRef, a); | ||
| 2611 | self.func.body.writeOperand(spec.IdRef, b); | ||
| 2612 | 2974 | ||
| 2613 | var i: usize = 0; | 2975 | var wip = try self.elementWise(ty); |
| 2614 | while (i < mask_len) : (i += 1) { | 2976 | defer wip.deinit(); |
| 2977 | for (wip.results, 0..) |*result_id, i| { | ||
| 2615 | const elem = try mask.elemValue(mod, i); | 2978 | const elem = try mask.elemValue(mod, i); |
| 2616 | if (elem.isUndef(mod)) { | 2979 | if (elem.isUndef(mod)) { |
| 2617 | self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF); | 2980 | result_id.* = try self.spv.constUndef(wip.scalar_ty_ref); |
| 2981 | continue; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | const index = elem.toSignedInt(mod); | ||
| 2985 | if (index >= 0) { | ||
| 2986 | result_id.* = try self.extractField(wip.scalar_ty, a, @intCast(index)); | ||
| 2618 | } else { | 2987 | } else { |
| 2619 | const int = elem.toSignedInt(mod); | 2988 | result_id.* = try self.extractField(wip.scalar_ty, b, @intCast(~index)); |
| 2620 | const unsigned = if (int >= 0) @as(u32, @intCast(int)) else @as(u32, @intCast(~int + a_len)); | ||
| 2621 | self.func.body.writeOperand(spec.LiteralInteger, unsigned); | ||
| 2622 | } | 2989 | } |
| 2623 | } | 2990 | } |
| 2624 | return result_id; | 2991 | return try wip.finalize(); |
| 2625 | } | 2992 | } |
| 2626 | 2993 | ||
| 2627 | fn indicesToIds(self: *DeclGen, indices: []const u32) ![]IdRef { | 2994 | fn indicesToIds(self: *DeclGen, indices: []const u32) ![]IdRef { |
| ... | @@ -2828,26 +3195,21 @@ const DeclGen = struct { | ... | @@ -2828,26 +3195,21 @@ const DeclGen = struct { |
| 2828 | return result_id; | 3195 | return result_id; |
| 2829 | }, | 3196 | }, |
| 2830 | .Vector => { | 3197 | .Vector => { |
| 2831 | const child_ty = ty.childType(mod); | 3198 | var wip = try self.elementWise(result_ty); |
| 2832 | const vector_len = ty.vectorLen(mod); | 3199 | defer wip.deinit(); |
| 2833 | 3200 | const scalar_ty = ty.scalarType(mod); | |
| 2834 | const constituents = try self.gpa.alloc(IdRef, vector_len); | 3201 | for (wip.results, 0..) |*result_id, i| { |
| 2835 | defer self.gpa.free(constituents); | 3202 | const lhs_elem_id = try wip.elementAt(ty, lhs_id, i); |
| 2836 | 3203 | const rhs_elem_id = try wip.elementAt(ty, rhs_id, i); | |
| 2837 | for (constituents, 0..) |*constituent, i| { | 3204 | result_id.* = try self.cmp(op, Type.bool, scalar_ty, lhs_elem_id, rhs_elem_id); |
| 2838 | const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i)); | ||
| 2839 | const rhs_index_id = try self.extractField(child_ty, cmp_rhs_id, @intCast(i)); | ||
| 2840 | const result_id = try self.cmp(op, Type.bool, child_ty, lhs_index_id, rhs_index_id); | ||
| 2841 | constituent.* = try self.convertToIndirect(Type.bool, result_id); | ||
| 2842 | } | 3205 | } |
| 2843 | 3206 | return wip.finalize(); | |
| 2844 | return try self.constructArray(result_ty, constituents); | ||
| 2845 | }, | 3207 | }, |
| 2846 | else => unreachable, | 3208 | else => unreachable, |
| 2847 | }; | 3209 | }; |
| 2848 | 3210 | ||
| 2849 | const opcode: Opcode = opcode: { | 3211 | const opcode: Opcode = opcode: { |
| 2850 | const info = try self.arithmeticTypeInfo(op_ty); | 3212 | const info = self.arithmeticTypeInfo(op_ty); |
| 2851 | const signedness = switch (info.class) { | 3213 | const signedness = switch (info.class) { |
| 2852 | .composite_integer => { | 3214 | .composite_integer => { |
| 2853 | return self.todo("binary operations for composite integers", .{}); | 3215 | return self.todo("binary operations for composite integers", .{}); |
| ... | @@ -2865,14 +3227,7 @@ const DeclGen = struct { | ... | @@ -2865,14 +3227,7 @@ const DeclGen = struct { |
| 2865 | .neq => .OpLogicalNotEqual, | 3227 | .neq => .OpLogicalNotEqual, |
| 2866 | else => unreachable, | 3228 | else => unreachable, |
| 2867 | }, | 3229 | }, |
| 2868 | .strange_integer => sign: { | 3230 | .integer, .strange_integer => info.signedness, |
| 2869 | const op_ty_ref = try self.resolveType(op_ty, .direct); | ||
| 2870 | // Mask operands before performing comparison. | ||
| 2871 | cmp_lhs_id = try self.normalizeInt(op_ty_ref, cmp_lhs_id, info); | ||
| 2872 | cmp_rhs_id = try self.normalizeInt(op_ty_ref, cmp_rhs_id, info); | ||
| 2873 | break :sign info.signedness; | ||
| 2874 | }, | ||
| 2875 | .integer => info.signedness, | ||
| 2876 | }; | 3231 | }; |
| 2877 | 3232 | ||
| 2878 | break :opcode switch (signedness) { | 3233 | break :opcode switch (signedness) { |
| ... | @@ -2942,50 +3297,64 @@ const DeclGen = struct { | ... | @@ -2942,50 +3297,64 @@ const DeclGen = struct { |
| 2942 | const mod = self.module; | 3297 | const mod = self.module; |
| 2943 | const src_ty_ref = try self.resolveType(src_ty, .direct); | 3298 | const src_ty_ref = try self.resolveType(src_ty, .direct); |
| 2944 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); | 3299 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); |
| 2945 | if (src_ty_ref == dst_ty_ref) { | 3300 | const src_key = self.spv.cache.lookup(src_ty_ref); |
| 2946 | return src_id; | 3301 | const dst_key = self.spv.cache.lookup(dst_ty_ref); |
| 2947 | } | ||
| 2948 | 3302 | ||
| 2949 | // TODO: Some more cases are missing here | 3303 | const result_id = blk: { |
| 2950 | // See fn bitCast in llvm.zig | 3304 | if (src_ty_ref == dst_ty_ref) { |
| 3305 | break :blk src_id; | ||
| 3306 | } | ||
| 2951 | 3307 | ||
| 2952 | if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { | 3308 | // TODO: Some more cases are missing here |
| 2953 | const result_id = self.spv.allocId(); | 3309 | // See fn bitCast in llvm.zig |
| 2954 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ | ||
| 2955 | .id_result_type = self.typeId(dst_ty_ref), | ||
| 2956 | .id_result = result_id, | ||
| 2957 | .integer_value = src_id, | ||
| 2958 | }); | ||
| 2959 | return result_id; | ||
| 2960 | } | ||
| 2961 | 3310 | ||
| 2962 | // We can only use OpBitcast for specific conversions: between numerical types, and | 3311 | if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { |
| 2963 | // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, | 3312 | const result_id = self.spv.allocId(); |
| 2964 | // otherwise use a temporary and perform a pointer cast. | 3313 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ |
| 2965 | const src_key = self.spv.cache.lookup(src_ty_ref); | 3314 | .id_result_type = self.typeId(dst_ty_ref), |
| 2966 | const dst_key = self.spv.cache.lookup(dst_ty_ref); | 3315 | .id_result = result_id, |
| 3316 | .integer_value = src_id, | ||
| 3317 | }); | ||
| 3318 | break :blk result_id; | ||
| 3319 | } | ||
| 2967 | 3320 | ||
| 2968 | if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { | 3321 | // We can only use OpBitcast for specific conversions: between numerical types, and |
| 2969 | const result_id = self.spv.allocId(); | 3322 | // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, |
| 3323 | // otherwise use a temporary and perform a pointer cast. | ||
| 3324 | if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { | ||
| 3325 | const result_id = self.spv.allocId(); | ||
| 3326 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | ||
| 3327 | .id_result_type = self.typeId(dst_ty_ref), | ||
| 3328 | .id_result = result_id, | ||
| 3329 | .operand = src_id, | ||
| 3330 | }); | ||
| 3331 | |||
| 3332 | break :blk result_id; | ||
| 3333 | } | ||
| 3334 | |||
| 3335 | const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function); | ||
| 3336 | |||
| 3337 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); | ||
| 3338 | try self.store(src_ty, tmp_id, src_id, .{}); | ||
| 3339 | const casted_ptr_id = self.spv.allocId(); | ||
| 2970 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 3340 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 2971 | .id_result_type = self.typeId(dst_ty_ref), | 3341 | .id_result_type = self.typeId(dst_ptr_ty_ref), |
| 2972 | .id_result = result_id, | 3342 | .id_result = casted_ptr_id, |
| 2973 | .operand = src_id, | 3343 | .operand = tmp_id, |
| 2974 | }); | 3344 | }); |
| 2975 | return result_id; | 3345 | break :blk try self.load(dst_ty, casted_ptr_id, .{}); |
| 2976 | } | 3346 | }; |
| 2977 | 3347 | ||
| 2978 | const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function); | 3348 | // Because strange integers use sign-extended representation, we may need to normalize |
| 3349 | // the result here. | ||
| 3350 | // TODO: This detail could cause stuff like @as(*const i1, @ptrCast(&@as(u1, 1))) to break | ||
| 3351 | // should we change the representation of strange integers? | ||
| 3352 | if (dst_ty.zigTypeTag(mod) == .Int) { | ||
| 3353 | const info = self.arithmeticTypeInfo(dst_ty); | ||
| 3354 | return try self.normalize(dst_ty_ref, result_id, info); | ||
| 3355 | } | ||
| 2979 | 3356 | ||
| 2980 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); | 3357 | return result_id; |
| 2981 | try self.store(src_ty, tmp_id, src_id, .{}); | ||
| 2982 | const casted_ptr_id = self.spv.allocId(); | ||
| 2983 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | ||
| 2984 | .id_result_type = self.typeId(dst_ptr_ty_ref), | ||
| 2985 | .id_result = casted_ptr_id, | ||
| 2986 | .operand = tmp_id, | ||
| 2987 | }); | ||
| 2988 | return try self.load(dst_ty, casted_ptr_id, .{}); | ||
| 2989 | } | 3358 | } |
| 2990 | 3359 | ||
| 2991 | fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 3360 | fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -3004,34 +3373,43 @@ const DeclGen = struct { | ... | @@ -3004,34 +3373,43 @@ const DeclGen = struct { |
| 3004 | const operand_id = try self.resolve(ty_op.operand); | 3373 | const operand_id = try self.resolve(ty_op.operand); |
| 3005 | const src_ty = self.typeOf(ty_op.operand); | 3374 | const src_ty = self.typeOf(ty_op.operand); |
| 3006 | const dst_ty = self.typeOfIndex(inst); | 3375 | const dst_ty = self.typeOfIndex(inst); |
| 3007 | const src_ty_ref = try self.resolveType(src_ty, .direct); | ||
| 3008 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); | ||
| 3009 | |||
| 3010 | const src_info = try self.arithmeticTypeInfo(src_ty); | ||
| 3011 | const dst_info = try self.arithmeticTypeInfo(dst_ty); | ||
| 3012 | 3376 | ||
| 3013 | // While intcast promises that the value already fits, the upper bits of a | 3377 | const src_info = self.arithmeticTypeInfo(src_ty); |
| 3014 | // strange integer may contain garbage. Therefore, mask/sign extend it before. | 3378 | const dst_info = self.arithmeticTypeInfo(dst_ty); |
| 3015 | const src_id = try self.normalizeInt(src_ty_ref, operand_id, src_info); | ||
| 3016 | 3379 | ||
| 3017 | if (src_info.backing_bits == dst_info.backing_bits) { | 3380 | if (src_info.backing_bits == dst_info.backing_bits) { |
| 3018 | return src_id; | 3381 | return operand_id; |
| 3019 | } | 3382 | } |
| 3020 | 3383 | ||
| 3021 | const result_id = self.spv.allocId(); | 3384 | var wip = try self.elementWise(dst_ty); |
| 3022 | switch (dst_info.signedness) { | 3385 | defer wip.deinit(); |
| 3023 | .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ | 3386 | for (wip.results, 0..) |*result_id, i| { |
| 3024 | .id_result_type = self.typeId(dst_ty_ref), | 3387 | const elem_id = try wip.elementAt(src_ty, operand_id, i); |
| 3025 | .id_result = result_id, | 3388 | const value_id = self.spv.allocId(); |
| 3026 | .signed_value = src_id, | 3389 | switch (dst_info.signedness) { |
| 3027 | }), | 3390 | .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ |
| 3028 | .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ | 3391 | .id_result_type = wip.scalar_ty_id, |
| 3029 | .id_result_type = self.typeId(dst_ty_ref), | 3392 | .id_result = value_id, |
| 3030 | .id_result = result_id, | 3393 | .signed_value = elem_id, |
| 3031 | .unsigned_value = src_id, | 3394 | }), |
| 3032 | }), | 3395 | .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ |
| 3396 | .id_result_type = wip.scalar_ty_id, | ||
| 3397 | .id_result = value_id, | ||
| 3398 | .unsigned_value = elem_id, | ||
| 3399 | }), | ||
| 3400 | } | ||
| 3401 | |||
| 3402 | // Make sure to normalize the result if shrinking. | ||
| 3403 | // Because strange ints are sign extended in their backing | ||
| 3404 | // type, we don't need to normalize when growing the type. The | ||
| 3405 | // representation is already the same. | ||
| 3406 | if (dst_info.bits < src_info.bits) { | ||
| 3407 | result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, dst_info); | ||
| 3408 | } else { | ||
| 3409 | result_id.* = value_id; | ||
| 3410 | } | ||
| 3033 | } | 3411 | } |
| 3034 | return result_id; | 3412 | return try wip.finalize(); |
| 3035 | } | 3413 | } |
| 3036 | 3414 | ||
| 3037 | fn intFromPtr(self: *DeclGen, operand_id: IdRef) !IdRef { | 3415 | fn intFromPtr(self: *DeclGen, operand_id: IdRef) !IdRef { |
| ... | @@ -3059,7 +3437,7 @@ const DeclGen = struct { | ... | @@ -3059,7 +3437,7 @@ const DeclGen = struct { |
| 3059 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3437 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3060 | const operand_ty = self.typeOf(ty_op.operand); | 3438 | const operand_ty = self.typeOf(ty_op.operand); |
| 3061 | const operand_id = try self.resolve(ty_op.operand); | 3439 | const operand_id = try self.resolve(ty_op.operand); |
| 3062 | const operand_info = try self.arithmeticTypeInfo(operand_ty); | 3440 | const operand_info = self.arithmeticTypeInfo(operand_ty); |
| 3063 | const dest_ty = self.typeOfIndex(inst); | 3441 | const dest_ty = self.typeOfIndex(inst); |
| 3064 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 3442 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 3065 | 3443 | ||
| ... | @@ -3085,7 +3463,7 @@ const DeclGen = struct { | ... | @@ -3085,7 +3463,7 @@ const DeclGen = struct { |
| 3085 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3463 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3086 | const operand_id = try self.resolve(ty_op.operand); | 3464 | const operand_id = try self.resolve(ty_op.operand); |
| 3087 | const dest_ty = self.typeOfIndex(inst); | 3465 | const dest_ty = self.typeOfIndex(inst); |
| 3088 | const dest_info = try self.arithmeticTypeInfo(dest_ty); | 3466 | const dest_info = self.arithmeticTypeInfo(dest_ty); |
| 3089 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 3467 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 3090 | 3468 | ||
| 3091 | const result_id = self.spv.allocId(); | 3469 | const result_id = self.spv.allocId(); |
| ... | @@ -3104,6 +3482,22 @@ const DeclGen = struct { | ... | @@ -3104,6 +3482,22 @@ const DeclGen = struct { |
| 3104 | return result_id; | 3482 | return result_id; |
| 3105 | } | 3483 | } |
| 3106 | 3484 | ||
| 3485 | fn airIntFromBool(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 3486 | if (self.liveness.isUnused(inst)) return null; | ||
| 3487 | |||
| 3488 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | ||
| 3489 | const operand_id = try self.resolve(un_op); | ||
| 3490 | const result_ty = self.typeOfIndex(inst); | ||
| 3491 | |||
| 3492 | var wip = try self.elementWise(result_ty); | ||
| 3493 | defer wip.deinit(); | ||
| 3494 | for (wip.results, 0..) |*result_id, i| { | ||
| 3495 | const elem_id = try wip.elementAt(Type.bool, operand_id, i); | ||
| 3496 | result_id.* = try self.intFromBool(wip.scalar_ty_ref, elem_id); | ||
| 3497 | } | ||
| 3498 | return try wip.finalize(); | ||
| 3499 | } | ||
| 3500 | |||
| 3107 | fn airFloatCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 3501 | fn airFloatCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 3108 | if (self.liveness.isUnused(inst)) return null; | 3502 | if (self.liveness.isUnused(inst)) return null; |
| 3109 | 3503 | ||
| ... | @@ -3126,31 +3520,31 @@ const DeclGen = struct { | ... | @@ -3126,31 +3520,31 @@ const DeclGen = struct { |
| 3126 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3520 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3127 | const operand_id = try self.resolve(ty_op.operand); | 3521 | const operand_id = try self.resolve(ty_op.operand); |
| 3128 | const result_ty = self.typeOfIndex(inst); | 3522 | const result_ty = self.typeOfIndex(inst); |
| 3129 | const result_ty_id = try self.resolveTypeId(result_ty); | 3523 | const info = self.arithmeticTypeInfo(result_ty); |
| 3130 | const info = try self.arithmeticTypeInfo(result_ty); | ||
| 3131 | 3524 | ||
| 3132 | const result_id = self.spv.allocId(); | 3525 | var wip = try self.elementWise(result_ty); |
| 3133 | switch (info.class) { | 3526 | defer wip.deinit(); |
| 3134 | .bool => { | 3527 | |
| 3135 | try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{ | 3528 | for (0..wip.results.len) |i| { |
| 3136 | .id_result_type = result_ty_id, | 3529 | const args = .{ |
| 3137 | .id_result = result_id, | 3530 | .id_result_type = wip.scalar_ty_id, |
| 3138 | .operand = operand_id, | 3531 | .id_result = wip.allocId(i), |
| 3139 | }); | 3532 | .operand = try wip.elementAt(result_ty, operand_id, i), |
| 3140 | }, | 3533 | }; |
| 3141 | .float => unreachable, | 3534 | switch (info.class) { |
| 3142 | .composite_integer => unreachable, // TODO | 3535 | .bool => { |
| 3143 | .strange_integer, .integer => { | 3536 | try self.func.body.emit(self.spv.gpa, .OpLogicalNot, args); |
| 3144 | // Note: strange integer bits will be masked before operations that do not hold under modulo. | 3537 | }, |
| 3145 | try self.func.body.emit(self.spv.gpa, .OpNot, .{ | 3538 | .float => unreachable, |
| 3146 | .id_result_type = result_ty_id, | 3539 | .composite_integer => unreachable, // TODO |
| 3147 | .id_result = result_id, | 3540 | .strange_integer, .integer => { |
| 3148 | .operand = operand_id, | 3541 | // Note: strange integer bits will be masked before operations that do not hold under modulo. |
| 3149 | }); | 3542 | try self.func.body.emit(self.spv.gpa, .OpNot, args); |
| 3150 | }, | 3543 | }, |
| 3544 | } | ||
| 3151 | } | 3545 | } |
| 3152 | 3546 | ||
| 3153 | return result_id; | 3547 | return try wip.finalize(); |
| 3154 | } | 3548 | } |
| 3155 | 3549 | ||
| 3156 | fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 3550 | fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -3213,7 +3607,6 @@ const DeclGen = struct { | ... | @@ -3213,7 +3607,6 @@ const DeclGen = struct { |
| 3213 | const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); | 3607 | const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); |
| 3214 | 3608 | ||
| 3215 | switch (result_ty.zigTypeTag(mod)) { | 3609 | switch (result_ty.zigTypeTag(mod)) { |
| 3216 | .Vector => unreachable, // TODO | ||
| 3217 | .Struct => { | 3610 | .Struct => { |
| 3218 | if (mod.typeToPackedStruct(result_ty)) |struct_type| { | 3611 | if (mod.typeToPackedStruct(result_ty)) |struct_type| { |
| 3219 | _ = struct_type; | 3612 | _ = struct_type; |
| ... | @@ -3261,7 +3654,7 @@ const DeclGen = struct { | ... | @@ -3261,7 +3654,7 @@ const DeclGen = struct { |
| 3261 | constituents[0..index], | 3654 | constituents[0..index], |
| 3262 | ); | 3655 | ); |
| 3263 | }, | 3656 | }, |
| 3264 | .Array => { | 3657 | .Vector, .Array => { |
| 3265 | const array_info = result_ty.arrayInfo(mod); | 3658 | const array_info = result_ty.arrayInfo(mod); |
| 3266 | const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); | 3659 | const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); |
| 3267 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); | 3660 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |
| ... | @@ -3433,6 +3826,28 @@ const DeclGen = struct { | ... | @@ -3433,6 +3826,28 @@ const DeclGen = struct { |
| 3433 | return try self.load(elem_ty, elem_ptr_id, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) }); | 3826 | return try self.load(elem_ty, elem_ptr_id, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) }); |
| 3434 | } | 3827 | } |
| 3435 | 3828 | ||
| 3829 | fn airVectorStoreElem(self: *DeclGen, inst: Air.Inst.Index) !void { | ||
| 3830 | const mod = self.module; | ||
| 3831 | const data = self.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; | ||
| 3832 | const extra = self.air.extraData(Air.Bin, data.payload).data; | ||
| 3833 | |||
| 3834 | const vector_ptr_ty = self.typeOf(data.vector_ptr); | ||
| 3835 | const vector_ty = vector_ptr_ty.childType(mod); | ||
| 3836 | const scalar_ty = vector_ty.scalarType(mod); | ||
| 3837 | |||
| 3838 | const storage_class = spvStorageClass(vector_ptr_ty.ptrAddressSpace(mod)); | ||
| 3839 | const scalar_ptr_ty_ref = try self.ptrType(scalar_ty, storage_class); | ||
| 3840 | |||
| 3841 | const vector_ptr = try self.resolve(data.vector_ptr); | ||
| 3842 | const index = try self.resolve(extra.lhs); | ||
| 3843 | const operand = try self.resolve(extra.rhs); | ||
| 3844 | |||
| 3845 | const elem_ptr_id = try self.accessChainId(scalar_ptr_ty_ref, vector_ptr, &.{index}); | ||
| 3846 | try self.store(scalar_ty, elem_ptr_id, operand, .{ | ||
| 3847 | .is_volatile = vector_ptr_ty.isVolatilePtr(mod), | ||
| 3848 | }); | ||
| 3849 | } | ||
| 3850 | |||
| 3436 | fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void { | 3851 | fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 3437 | const mod = self.module; | 3852 | const mod = self.module; |
| 3438 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 3853 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | @@ -4424,20 +4839,24 @@ const DeclGen = struct { | ... | @@ -4424,20 +4839,24 @@ const DeclGen = struct { |
| 4424 | return try self.constructStruct(err_union_ty, &types, &members); | 4839 | return try self.constructStruct(err_union_ty, &types, &members); |
| 4425 | } | 4840 | } |
| 4426 | 4841 | ||
| 4427 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { | 4842 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { |
| 4428 | if (self.liveness.isUnused(inst)) return null; | 4843 | if (self.liveness.isUnused(inst)) return null; |
| 4429 | 4844 | ||
| 4430 | const mod = self.module; | 4845 | const mod = self.module; |
| 4431 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 4846 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 4432 | const operand_id = try self.resolve(un_op); | 4847 | const operand_id = try self.resolve(un_op); |
| 4433 | const optional_ty = self.typeOf(un_op); | 4848 | const operand_ty = self.typeOf(un_op); |
| 4434 | 4849 | const optional_ty = if (is_pointer) operand_ty.childType(mod) else operand_ty; | |
| 4435 | const payload_ty = optional_ty.optionalChild(mod); | 4850 | const payload_ty = optional_ty.optionalChild(mod); |
| 4436 | 4851 | ||
| 4437 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 4852 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 4438 | 4853 | ||
| 4439 | if (optional_ty.optionalReprIsPayload(mod)) { | 4854 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 4440 | // Pointer payload represents nullability: pointer or slice. | 4855 | // Pointer payload represents nullability: pointer or slice. |
| 4856 | const loaded_id = if (is_pointer) | ||
| 4857 | try self.load(optional_ty, operand_id, .{}) | ||
| 4858 | else | ||
| 4859 | operand_id; | ||
| 4441 | 4860 | ||
| 4442 | const ptr_ty = if (payload_ty.isSlice(mod)) | 4861 | const ptr_ty = if (payload_ty.isSlice(mod)) |
| 4443 | payload_ty.slicePtrFieldType(mod) | 4862 | payload_ty.slicePtrFieldType(mod) |
| ... | @@ -4445,9 +4864,9 @@ const DeclGen = struct { | ... | @@ -4445,9 +4864,9 @@ const DeclGen = struct { |
| 4445 | payload_ty; | 4864 | payload_ty; |
| 4446 | 4865 | ||
| 4447 | const ptr_id = if (payload_ty.isSlice(mod)) | 4866 | const ptr_id = if (payload_ty.isSlice(mod)) |
| 4448 | try self.extractField(ptr_ty, operand_id, 0) | 4867 | try self.extractField(ptr_ty, loaded_id, 0) |
| 4449 | else | 4868 | else |
| 4450 | operand_id; | 4869 | loaded_id; |
| 4451 | 4870 | ||
| 4452 | const payload_ty_ref = try self.resolveType(ptr_ty, .direct); | 4871 | const payload_ty_ref = try self.resolveType(ptr_ty, .direct); |
| 4453 | const null_id = try self.spv.constNull(payload_ty_ref); | 4872 | const null_id = try self.spv.constNull(payload_ty_ref); |
| ... | @@ -4458,13 +4877,26 @@ const DeclGen = struct { | ... | @@ -4458,13 +4877,26 @@ const DeclGen = struct { |
| 4458 | return try self.cmp(op, Type.bool, ptr_ty, ptr_id, null_id); | 4877 | return try self.cmp(op, Type.bool, ptr_ty, ptr_id, null_id); |
| 4459 | } | 4878 | } |
| 4460 | 4879 | ||
| 4461 | const is_non_null_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | 4880 | const is_non_null_id = blk: { |
| 4462 | try self.extractField(Type.bool, operand_id, 1) | 4881 | if (is_pointer) { |
| 4463 | else | 4882 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4464 | // Optional representation is bool indicating whether the optional is set | 4883 | const storage_class = spvStorageClass(operand_ty.ptrAddressSpace(mod)); |
| 4465 | // Optionals with no payload are represented as an (indirect) bool, so convert | 4884 | const bool_ptr_ty = try self.ptrType(Type.bool, storage_class); |
| 4466 | // it back to the direct bool here. | 4885 | const tag_ptr_id = try self.accessChain(bool_ptr_ty, operand_id, &.{1}); |
| 4467 | try self.convertToDirect(Type.bool, operand_id); | 4886 | break :blk try self.load(Type.bool, tag_ptr_id, .{}); |
| 4887 | } | ||
| 4888 | |||
| 4889 | break :blk try self.load(Type.bool, operand_id, .{}); | ||
| 4890 | } | ||
| 4891 | |||
| 4892 | break :blk if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) | ||
| 4893 | try self.extractField(Type.bool, operand_id, 1) | ||
| 4894 | else | ||
| 4895 | // Optional representation is bool indicating whether the optional is set | ||
| 4896 | // Optionals with no payload are represented as an (indirect) bool, so convert | ||
| 4897 | // it back to the direct bool here. | ||
| 4898 | try self.convertToDirect(Type.bool, operand_id); | ||
| 4899 | }; | ||
| 4468 | 4900 | ||
| 4469 | return switch (pred) { | 4901 | return switch (pred) { |
| 4470 | .is_null => blk: { | 4902 | .is_null => blk: { |
| ... | @@ -4535,6 +4967,32 @@ const DeclGen = struct { | ... | @@ -4535,6 +4967,32 @@ const DeclGen = struct { |
| 4535 | return try self.extractField(payload_ty, operand_id, 0); | 4967 | return try self.extractField(payload_ty, operand_id, 0); |
| 4536 | } | 4968 | } |
| 4537 | 4969 | ||
| 4970 | fn airUnwrapOptionalPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | ||
| 4971 | if (self.liveness.isUnused(inst)) return null; | ||
| 4972 | |||
| 4973 | const mod = self.module; | ||
| 4974 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | ||
| 4975 | const operand_id = try self.resolve(ty_op.operand); | ||
| 4976 | const operand_ty = self.typeOf(ty_op.operand); | ||
| 4977 | const optional_ty = operand_ty.childType(mod); | ||
| 4978 | const payload_ty = optional_ty.optionalChild(mod); | ||
| 4979 | const result_ty = self.typeOfIndex(inst); | ||
| 4980 | const result_ty_ref = try self.resolveType(result_ty, .direct); | ||
| 4981 | |||
| 4982 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | ||
| 4983 | // There is no payload, but we still need to return a valid pointer. | ||
| 4984 | // We can just return anything here, so just return a pointer to the operand. | ||
| 4985 | return try self.bitCast(result_ty, operand_ty, operand_id); | ||
| 4986 | } | ||
| 4987 | |||
| 4988 | if (optional_ty.optionalReprIsPayload(mod)) { | ||
| 4989 | // They are the same value. | ||
| 4990 | return try self.bitCast(result_ty, operand_ty, operand_id); | ||
| 4991 | } | ||
| 4992 | |||
| 4993 | return try self.accessChain(result_ty_ref, operand_id, &.{0}); | ||
| 4994 | } | ||
| 4995 | |||
| 4538 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 4996 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 4539 | if (self.liveness.isUnused(inst)) return null; | 4997 | if (self.liveness.isUnused(inst)) return null; |
| 4540 | 4998 |
test/behavior/abs.zig+2-6| ... | @@ -7,7 +7,6 @@ test "@abs integers" { | ... | @@ -7,7 +7,6 @@ test "@abs integers" { |
| 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 8 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 11 | 10 | ||
| 12 | try comptime testAbsIntegers(); | 11 | try comptime testAbsIntegers(); |
| 13 | try testAbsIntegers(); | 12 | try testAbsIntegers(); |
| ... | @@ -95,7 +94,6 @@ test "@abs floats" { | ... | @@ -95,7 +94,6 @@ test "@abs floats" { |
| 95 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 94 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 96 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 95 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 97 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 96 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 98 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 99 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 97 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 100 | 98 | ||
| 101 | try comptime testAbsFloats(f16); | 99 | try comptime testAbsFloats(f16); |
| ... | @@ -105,9 +103,9 @@ test "@abs floats" { | ... | @@ -105,9 +103,9 @@ test "@abs floats" { |
| 105 | try comptime testAbsFloats(f64); | 103 | try comptime testAbsFloats(f64); |
| 106 | try testAbsFloats(f64); | 104 | try testAbsFloats(f64); |
| 107 | try comptime testAbsFloats(f80); | 105 | try comptime testAbsFloats(f80); |
| 108 | if (builtin.zig_backend != .stage2_wasm) try testAbsFloats(f80); | 106 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80); |
| 109 | try comptime testAbsFloats(f128); | 107 | try comptime testAbsFloats(f128); |
| 110 | if (builtin.zig_backend != .stage2_wasm) try testAbsFloats(f128); | 108 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128); |
| 111 | } | 109 | } |
| 112 | 110 | ||
| 113 | fn testAbsFloats(comptime T: type) !void { | 111 | fn testAbsFloats(comptime T: type) !void { |
| ... | @@ -155,7 +153,6 @@ test "@abs int vectors" { | ... | @@ -155,7 +153,6 @@ test "@abs int vectors" { |
| 155 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 153 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 156 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 154 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 157 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 155 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 158 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 159 | 156 | ||
| 160 | try comptime testAbsIntVectors(1); | 157 | try comptime testAbsIntVectors(1); |
| 161 | try testAbsIntVectors(1); | 158 | try testAbsIntVectors(1); |
| ... | @@ -224,7 +221,6 @@ test "@abs unsigned int vectors" { | ... | @@ -224,7 +221,6 @@ test "@abs unsigned int vectors" { |
| 224 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 221 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 225 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 222 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 226 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 223 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 227 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 228 | 224 | ||
| 229 | try comptime testAbsUnsignedIntVectors(1); | 225 | try comptime testAbsUnsignedIntVectors(1); |
| 230 | try testAbsUnsignedIntVectors(1); | 226 | try testAbsUnsignedIntVectors(1); |
test/behavior/align.zig+3-4| ... | @@ -18,7 +18,6 @@ test "global variable alignment" { | ... | @@ -18,7 +18,6 @@ test "global variable alignment" { |
| 18 | test "large alignment of local constant" { | 18 | test "large alignment of local constant" { |
| 19 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 19 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 21 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky | ||
| 22 | 21 | ||
| 23 | const x: f32 align(128) = 12.34; | 22 | const x: f32 align(128) = 12.34; |
| 24 | try std.testing.expect(@intFromPtr(&x) % 128 == 0); | 23 | try std.testing.expect(@intFromPtr(&x) % 128 == 0); |
| ... | @@ -27,7 +26,7 @@ test "large alignment of local constant" { | ... | @@ -27,7 +26,7 @@ test "large alignment of local constant" { |
| 27 | test "slicing array of length 1 can not assume runtime index is always zero" { | 26 | test "slicing array of length 1 can not assume runtime index is always zero" { |
| 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 27 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 29 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 28 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 30 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 29 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky |
| 31 | 30 | ||
| 32 | var runtime_index: usize = 1; | 31 | var runtime_index: usize = 1; |
| 33 | _ = &runtime_index; | 32 | _ = &runtime_index; |
| ... | @@ -512,7 +511,7 @@ test "struct field explicit alignment" { | ... | @@ -512,7 +511,7 @@ test "struct field explicit alignment" { |
| 512 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 511 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 513 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 512 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 514 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 513 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 515 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 514 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky |
| 516 | 515 | ||
| 517 | const S = struct { | 516 | const S = struct { |
| 518 | const Node = struct { | 517 | const Node = struct { |
| ... | @@ -581,7 +580,7 @@ test "comptime alloc alignment" { | ... | @@ -581,7 +580,7 @@ test "comptime alloc alignment" { |
| 581 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 580 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 582 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 581 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 583 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 582 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 584 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 583 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky |
| 585 | if (builtin.zig_backend == .stage2_llvm and builtin.target.cpu.arch == .x86) { | 584 | if (builtin.zig_backend == .stage2_llvm and builtin.target.cpu.arch == .x86) { |
| 586 | // https://github.com/ziglang/zig/issues/18034 | 585 | // https://github.com/ziglang/zig/issues/18034 |
| 587 | return error.SkipZigTest; | 586 | return error.SkipZigTest; |
test/behavior/array.zig-2| ... | @@ -768,8 +768,6 @@ test "array init with no result pointer sets field result types" { | ... | @@ -768,8 +768,6 @@ test "array init with no result pointer sets field result types" { |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | test "runtime side-effects in comptime-known array init" { | 770 | test "runtime side-effects in comptime-known array init" { |
| 771 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 772 | |||
| 773 | var side_effects: u4 = 0; | 771 | var side_effects: u4 = 0; |
| 774 | const init = [4]u4{ | 772 | const init = [4]u4{ |
| 775 | blk: { | 773 | blk: { |
test/behavior/basic.zig+1| ... | @@ -1222,6 +1222,7 @@ test "integer compare" { | ... | @@ -1222,6 +1222,7 @@ test "integer compare" { |
| 1222 | 1222 | ||
| 1223 | test "reference to inferred local variable works as expected" { | 1223 | test "reference to inferred local variable works as expected" { |
| 1224 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1224 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1225 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1225 | 1226 | ||
| 1226 | const Crasher = struct { | 1227 | const Crasher = struct { |
| 1227 | lets_crash: u64 = 0, | 1228 | lets_crash: u64 = 0, |
test/behavior/bool.zig-2| ... | @@ -9,8 +9,6 @@ test "bool literals" { | ... | @@ -9,8 +9,6 @@ test "bool literals" { |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | test "cast bool to int" { | 11 | test "cast bool to int" { |
| 12 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 13 | |||
| 14 | const t = true; | 12 | const t = true; |
| 15 | const f = false; | 13 | const f = false; |
| 16 | try expectEqual(@as(u32, 1), @intFromBool(t)); | 14 | try expectEqual(@as(u32, 1), @intFromBool(t)); |
test/behavior/builtin_functions_returning_void_or_noreturn.zig+1| ... | @@ -11,6 +11,7 @@ test { | ... | @@ -11,6 +11,7 @@ test { |
| 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 13 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | 13 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 14 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 14 | 15 | ||
| 15 | var val: u8 = undefined; | 16 | var val: u8 = undefined; |
| 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .Unordered)); | 17 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .Unordered)); |
test/behavior/cast.zig+1-11| ... | @@ -605,7 +605,6 @@ test "@intCast on vector" { | ... | @@ -605,7 +605,6 @@ test "@intCast on vector" { |
| 605 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 605 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 606 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 606 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 607 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 607 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 608 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 609 | 608 | ||
| 610 | const S = struct { | 609 | const S = struct { |
| 611 | fn doTheTest() !void { | 610 | fn doTheTest() !void { |
| ... | @@ -760,6 +759,7 @@ test "peer type resolution: error union and error set" { | ... | @@ -760,6 +759,7 @@ test "peer type resolution: error union and error set" { |
| 760 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 759 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 761 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 760 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 762 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 761 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 762 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 763 | 763 | ||
| 764 | const a: error{Three} = undefined; | 764 | const a: error{Three} = undefined; |
| 765 | const b: error{ One, Two }!u32 = undefined; | 765 | const b: error{ One, Two }!u32 = undefined; |
| ... | @@ -1247,7 +1247,6 @@ test "implicit cast from *[N]T to ?[*]T" { | ... | @@ -1247,7 +1247,6 @@ test "implicit cast from *[N]T to ?[*]T" { |
| 1247 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1247 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1248 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1248 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1249 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1249 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1250 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1251 | 1250 | ||
| 1252 | var x: ?[*]u16 = null; | 1251 | var x: ?[*]u16 = null; |
| 1253 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | 1252 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; |
| ... | @@ -1732,7 +1731,6 @@ test "peer type resolution: array with smaller child type and vector with larger | ... | @@ -1732,7 +1731,6 @@ test "peer type resolution: array with smaller child type and vector with larger |
| 1732 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1731 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1733 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1732 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1734 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1733 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1735 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 1736 | 1734 | ||
| 1737 | var arr: [2]u8 = .{ 0, 1 }; | 1735 | var arr: [2]u8 = .{ 0, 1 }; |
| 1738 | var vec: @Vector(2, u64) = .{ 2, 3 }; | 1736 | var vec: @Vector(2, u64) = .{ 2, 3 }; |
| ... | @@ -2320,7 +2318,6 @@ test "@floatCast on vector" { | ... | @@ -2320,7 +2318,6 @@ test "@floatCast on vector" { |
| 2320 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2318 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2321 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2319 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2322 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2320 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2323 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2324 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 2321 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 2325 | 2322 | ||
| 2326 | const S = struct { | 2323 | const S = struct { |
| ... | @@ -2341,7 +2338,6 @@ test "@ptrFromInt on vector" { | ... | @@ -2341,7 +2338,6 @@ test "@ptrFromInt on vector" { |
| 2341 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2338 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2342 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2343 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2340 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2344 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2345 | 2341 | ||
| 2346 | const S = struct { | 2342 | const S = struct { |
| 2347 | fn doTheTest() !void { | 2343 | fn doTheTest() !void { |
| ... | @@ -2365,7 +2361,6 @@ test "@intFromPtr on vector" { | ... | @@ -2365,7 +2361,6 @@ test "@intFromPtr on vector" { |
| 2365 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2361 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2366 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2362 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2367 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2363 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2368 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2369 | 2364 | ||
| 2370 | const S = struct { | 2365 | const S = struct { |
| 2371 | fn doTheTest() !void { | 2366 | fn doTheTest() !void { |
| ... | @@ -2389,7 +2384,6 @@ test "@floatFromInt on vector" { | ... | @@ -2389,7 +2384,6 @@ test "@floatFromInt on vector" { |
| 2389 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2384 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2390 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2385 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2391 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2386 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2392 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2393 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 2387 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 2394 | 2388 | ||
| 2395 | const S = struct { | 2389 | const S = struct { |
| ... | @@ -2410,7 +2404,6 @@ test "@intFromFloat on vector" { | ... | @@ -2410,7 +2404,6 @@ test "@intFromFloat on vector" { |
| 2410 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2404 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2411 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2405 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2412 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2406 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2413 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2414 | 2407 | ||
| 2415 | const S = struct { | 2408 | const S = struct { |
| 2416 | fn doTheTest() !void { | 2409 | fn doTheTest() !void { |
| ... | @@ -2430,7 +2423,6 @@ test "@intFromBool on vector" { | ... | @@ -2430,7 +2423,6 @@ test "@intFromBool on vector" { |
| 2430 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2423 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2431 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2424 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2432 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2425 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2433 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2434 | 2426 | ||
| 2435 | const S = struct { | 2427 | const S = struct { |
| 2436 | fn doTheTest() !void { | 2428 | fn doTheTest() !void { |
| ... | @@ -2468,7 +2460,6 @@ test "@as does not corrupt values with incompatible representations" { | ... | @@ -2468,7 +2460,6 @@ test "@as does not corrupt values with incompatible representations" { |
| 2468 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2460 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2469 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2461 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2470 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2462 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2471 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2472 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 2463 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 2473 | 2464 | ||
| 2474 | const x: f32 = @as(f16, blk: { | 2465 | const x: f32 = @as(f16, blk: { |
| ... | @@ -2510,7 +2501,6 @@ test "@intCast vector of signed integer" { | ... | @@ -2510,7 +2501,6 @@ test "@intCast vector of signed integer" { |
| 2510 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2501 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2511 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 2502 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 2512 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2503 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2513 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 2514 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 2504 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 2515 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 2505 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 2516 | 2506 |
test/behavior/destructure.zig+1| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 3 | const expect = std.testing.expect; | 4 | const expect = std.testing.expect; |
| 4 | 5 |
test/behavior/duplicated_test_names.zig+2| ... | @@ -15,5 +15,7 @@ comptime { | ... | @@ -15,5 +15,7 @@ comptime { |
| 15 | test "thingy" {} | 15 | test "thingy" {} |
| 16 | 16 | ||
| 17 | test thingy { | 17 | test thingy { |
| 18 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 19 | |||
| 18 | if (thingy(1, 2) != 3) unreachable; | 20 | if (thingy(1, 2) != 3) unreachable; |
| 19 | } | 21 | } |
test/behavior/eval.zig-1| ... | @@ -489,7 +489,6 @@ test "comptime bitwise operators" { | ... | @@ -489,7 +489,6 @@ test "comptime bitwise operators" { |
| 489 | 489 | ||
| 490 | test "comptime shlWithOverflow" { | 490 | test "comptime shlWithOverflow" { |
| 491 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 491 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 492 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 493 | 492 | ||
| 494 | const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0]; | 493 | const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0]; |
| 495 | var a = ~@as(u64, 0); | 494 | var a = ~@as(u64, 0); |
test/behavior/export_builtin.zig-3| ... | @@ -6,7 +6,6 @@ test "exporting enum type and value" { | ... | @@ -6,7 +6,6 @@ test "exporting enum type and value" { |
| 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 8 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 8 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 9 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 10 | 9 | ||
| 11 | const S = struct { | 10 | const S = struct { |
| 12 | const E = enum(c_int) { one, two }; | 11 | const E = enum(c_int) { one, two }; |
| ... | @@ -22,7 +21,6 @@ test "exporting with internal linkage" { | ... | @@ -22,7 +21,6 @@ test "exporting with internal linkage" { |
| 22 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 22 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 24 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 23 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 25 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 26 | 24 | ||
| 27 | const S = struct { | 25 | const S = struct { |
| 28 | fn foo() callconv(.C) void {} | 26 | fn foo() callconv(.C) void {} |
| ... | @@ -37,7 +35,6 @@ test "exporting using field access" { | ... | @@ -37,7 +35,6 @@ test "exporting using field access" { |
| 37 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 35 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 38 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 36 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 39 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 37 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 40 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 41 | 38 | ||
| 42 | const S = struct { | 39 | const S = struct { |
| 43 | const Inner = struct { | 40 | const Inner = struct { |
test/behavior/export_keyword.zig+1| ... | @@ -23,6 +23,7 @@ const PackedUnion = packed union { | ... | @@ -23,6 +23,7 @@ const PackedUnion = packed union { |
| 23 | 23 | ||
| 24 | test "packed struct, enum, union parameters in extern function" { | 24 | test "packed struct, enum, union parameters in extern function" { |
| 25 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 25 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 26 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 26 | 27 | ||
| 27 | testPackedStuff(&(PackedStruct{ | 28 | testPackedStuff(&(PackedStruct{ |
| 28 | .a = 1, | 29 | .a = 1, |
test/behavior/extern.zig+2| ... | @@ -5,6 +5,7 @@ const expect = std.testing.expect; | ... | @@ -5,6 +5,7 @@ const expect = std.testing.expect; |
| 5 | test "anyopaque extern symbol" { | 5 | test "anyopaque extern symbol" { |
| 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 7 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 7 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 8 | 9 | ||
| 9 | const a = @extern(*anyopaque, .{ .name = "a_mystery_symbol" }); | 10 | const a = @extern(*anyopaque, .{ .name = "a_mystery_symbol" }); |
| 10 | const b: *i32 = @alignCast(@ptrCast(a)); | 11 | const b: *i32 = @alignCast(@ptrCast(a)); |
| ... | @@ -17,6 +18,7 @@ test "function extern symbol" { | ... | @@ -17,6 +18,7 @@ test "function extern symbol" { |
| 17 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 18 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 18 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 19 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 19 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 21 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 20 | 22 | ||
| 21 | const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" }); | 23 | const a = @extern(*const fn () callconv(.C) i32, .{ .name = "a_mystery_function" }); |
| 22 | try expect(a() == 4567); | 24 | try expect(a() == 4567); |
test/behavior/floatop.zig-3| ... | @@ -969,7 +969,6 @@ test "@abs f16" { | ... | @@ -969,7 +969,6 @@ test "@abs f16" { |
| 969 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 969 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 970 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 970 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 971 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 971 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 972 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 973 | 972 | ||
| 974 | try testFabs(f16); | 973 | try testFabs(f16); |
| 975 | try comptime testFabs(f16); | 974 | try comptime testFabs(f16); |
| ... | @@ -979,7 +978,6 @@ test "@abs f32/f64" { | ... | @@ -979,7 +978,6 @@ test "@abs f32/f64" { |
| 979 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 978 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 980 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 979 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 981 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 980 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 982 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 983 | 981 | ||
| 984 | try testFabs(f32); | 982 | try testFabs(f32); |
| 985 | try comptime testFabs(f32); | 983 | try comptime testFabs(f32); |
| ... | @@ -1070,7 +1068,6 @@ fn testFabs(comptime T: type) !void { | ... | @@ -1070,7 +1068,6 @@ fn testFabs(comptime T: type) !void { |
| 1070 | test "@abs with vectors" { | 1068 | test "@abs with vectors" { |
| 1071 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1069 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1072 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1070 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1073 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1074 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1071 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1075 | 1072 | ||
| 1076 | try testFabsWithVectors(); | 1073 | try testFabsWithVectors(); |
test/behavior/for.zig+1| ... | @@ -456,6 +456,7 @@ test "inline for on tuple pointer" { | ... | @@ -456,6 +456,7 @@ test "inline for on tuple pointer" { |
| 456 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 456 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 457 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 457 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 458 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 458 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 459 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 459 | 460 | ||
| 460 | const S = struct { u32, u32, u32 }; | 461 | const S = struct { u32, u32, u32 }; |
| 461 | var s: S = .{ 100, 200, 300 }; | 462 | var s: S = .{ 100, 200, 300 }; |
test/behavior/globals.zig-2| ... | @@ -8,7 +8,6 @@ test "store to global array" { | ... | @@ -8,7 +8,6 @@ test "store to global array" { |
| 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 11 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 12 | 11 | ||
| 13 | try expect(pos[1] == 0.0); | 12 | try expect(pos[1] == 0.0); |
| 14 | pos = [2]f32{ 0.0, 1.0 }; | 13 | pos = [2]f32{ 0.0, 1.0 }; |
| ... | @@ -21,7 +20,6 @@ test "store to global vector" { | ... | @@ -21,7 +20,6 @@ test "store to global vector" { |
| 21 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 22 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 23 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 22 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 24 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 25 | 23 | ||
| 26 | try expect(vpos[1] == 0.0); | 24 | try expect(vpos[1] == 0.0); |
| 27 | vpos = @Vector(2, f32){ 0.0, 1.0 }; | 25 | vpos = @Vector(2, f32){ 0.0, 1.0 }; |
test/behavior/hasdecl.zig+5| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 3 | 4 | ||
| 4 | const Foo = @import("hasdecl/foo.zig"); | 5 | const Foo = @import("hasdecl/foo.zig"); |
| ... | @@ -11,6 +12,8 @@ const Bar = struct { | ... | @@ -11,6 +12,8 @@ const Bar = struct { |
| 11 | }; | 12 | }; |
| 12 | 13 | ||
| 13 | test "@hasDecl" { | 14 | test "@hasDecl" { |
| 15 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 16 | |||
| 14 | try expect(@hasDecl(Foo, "public_thing")); | 17 | try expect(@hasDecl(Foo, "public_thing")); |
| 15 | try expect(!@hasDecl(Foo, "private_thing")); | 18 | try expect(!@hasDecl(Foo, "private_thing")); |
| 16 | try expect(!@hasDecl(Foo, "no_thing")); | 19 | try expect(!@hasDecl(Foo, "no_thing")); |
| ... | @@ -21,6 +24,8 @@ test "@hasDecl" { | ... | @@ -21,6 +24,8 @@ test "@hasDecl" { |
| 21 | } | 24 | } |
| 22 | 25 | ||
| 23 | test "@hasDecl using a sliced string literal" { | 26 | test "@hasDecl using a sliced string literal" { |
| 27 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 28 | |||
| 24 | try expect(@hasDecl(@This(), "std") == true); | 29 | try expect(@hasDecl(@This(), "std") == true); |
| 25 | try expect(@hasDecl(@This(), "std"[0..0]) == false); | 30 | try expect(@hasDecl(@This(), "std"[0..0]) == false); |
| 26 | try expect(@hasDecl(@This(), "std"[0..1]) == false); | 31 | try expect(@hasDecl(@This(), "std"[0..1]) == false); |
test/behavior/import.zig+9| ... | @@ -1,17 +1,24 @@ | ... | @@ -1,17 +1,24 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | 4 | const expectEqual = std.testing.expectEqual; |
| 4 | const a_namespace = @import("import/a_namespace.zig"); | 5 | const a_namespace = @import("import/a_namespace.zig"); |
| 5 | 6 | ||
| 6 | test "call fn via namespace lookup" { | 7 | test "call fn via namespace lookup" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 7 | try expect(@as(i32, 1234) == a_namespace.foo()); | 10 | try expect(@as(i32, 1234) == a_namespace.foo()); |
| 8 | } | 11 | } |
| 9 | 12 | ||
| 10 | test "importing the same thing gives the same import" { | 13 | test "importing the same thing gives the same import" { |
| 14 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 15 | |||
| 11 | try expect(@import("std") == @import("std")); | 16 | try expect(@import("std") == @import("std")); |
| 12 | } | 17 | } |
| 13 | 18 | ||
| 14 | test "import in non-toplevel scope" { | 19 | test "import in non-toplevel scope" { |
| 20 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 21 | |||
| 15 | const S = struct { | 22 | const S = struct { |
| 16 | usingnamespace @import("import/a_namespace.zig"); | 23 | usingnamespace @import("import/a_namespace.zig"); |
| 17 | }; | 24 | }; |
| ... | @@ -19,5 +26,7 @@ test "import in non-toplevel scope" { | ... | @@ -19,5 +26,7 @@ test "import in non-toplevel scope" { |
| 19 | } | 26 | } |
| 20 | 27 | ||
| 21 | test "import empty file" { | 28 | test "import empty file" { |
| 29 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 30 | |||
| 22 | _ = @import("import/empty.zig"); | 31 | _ = @import("import/empty.zig"); |
| 23 | } | 32 | } |
test/behavior/int_div.zig+2| ... | @@ -6,6 +6,7 @@ test "integer division" { | ... | @@ -6,6 +6,7 @@ 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; // TODO | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | 10 | ||
| 10 | try testDivision(); | 11 | try testDivision(); |
| 11 | try comptime testDivision(); | 12 | try comptime testDivision(); |
| ... | @@ -96,6 +97,7 @@ test "large integer division" { | ... | @@ -96,6 +97,7 @@ test "large integer division" { |
| 96 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 97 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 97 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 98 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 98 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 99 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 100 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 99 | 101 | ||
| 100 | { | 102 | { |
| 101 | var numerator: u256 = 99999999999999999997315645440; | 103 | var numerator: u256 = 99999999999999999997315645440; |
test/behavior/math.zig-10| ... | @@ -602,7 +602,6 @@ fn testUnsignedNegationWrappingEval(x: u16) !void { | ... | @@ -602,7 +602,6 @@ fn testUnsignedNegationWrappingEval(x: u16) !void { |
| 602 | test "negation wrapping" { | 602 | test "negation wrapping" { |
| 603 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 603 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 604 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 604 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 605 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 606 | 605 | ||
| 607 | try expectEqual(@as(u1, 1), negateWrap(u1, 1)); | 606 | try expectEqual(@as(u1, 1), negateWrap(u1, 1)); |
| 608 | } | 607 | } |
| ... | @@ -649,8 +648,6 @@ test "bit shift a u1" { | ... | @@ -649,8 +648,6 @@ test "bit shift a u1" { |
| 649 | } | 648 | } |
| 650 | 649 | ||
| 651 | test "truncating shift right" { | 650 | test "truncating shift right" { |
| 652 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 653 | |||
| 654 | try testShrTrunc(maxInt(u16)); | 651 | try testShrTrunc(maxInt(u16)); |
| 655 | try comptime testShrTrunc(maxInt(u16)); | 652 | try comptime testShrTrunc(maxInt(u16)); |
| 656 | } | 653 | } |
| ... | @@ -772,7 +769,6 @@ test "@addWithOverflow" { | ... | @@ -772,7 +769,6 @@ test "@addWithOverflow" { |
| 772 | test "small int addition" { | 769 | test "small int addition" { |
| 773 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 770 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 774 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 771 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 775 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 776 | 772 | ||
| 777 | var x: u2 = 0; | 773 | var x: u2 = 0; |
| 778 | try expect(x == 0); | 774 | try expect(x == 0); |
| ... | @@ -1330,8 +1326,6 @@ fn testShlTrunc(x: u16) !void { | ... | @@ -1330,8 +1326,6 @@ fn testShlTrunc(x: u16) !void { |
| 1330 | } | 1326 | } |
| 1331 | 1327 | ||
| 1332 | test "exact shift left" { | 1328 | test "exact shift left" { |
| 1333 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1334 | |||
| 1335 | try testShlExact(0b00110101); | 1329 | try testShlExact(0b00110101); |
| 1336 | try comptime testShlExact(0b00110101); | 1330 | try comptime testShlExact(0b00110101); |
| 1337 | 1331 | ||
| ... | @@ -1343,8 +1337,6 @@ fn testShlExact(x: u8) !void { | ... | @@ -1343,8 +1337,6 @@ fn testShlExact(x: u8) !void { |
| 1343 | } | 1337 | } |
| 1344 | 1338 | ||
| 1345 | test "exact shift right" { | 1339 | test "exact shift right" { |
| 1346 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1347 | |||
| 1348 | try testShrExact(0b10110100); | 1340 | try testShrExact(0b10110100); |
| 1349 | try comptime testShrExact(0b10110100); | 1341 | try comptime testShrExact(0b10110100); |
| 1350 | } | 1342 | } |
| ... | @@ -1570,7 +1562,6 @@ test "vector integer addition" { | ... | @@ -1570,7 +1562,6 @@ test "vector integer addition" { |
| 1570 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1562 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1571 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1563 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1572 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1564 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1573 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1574 | 1565 | ||
| 1575 | const S = struct { | 1566 | const S = struct { |
| 1576 | fn doTheTest() !void { | 1567 | fn doTheTest() !void { |
| ... | @@ -1693,7 +1684,6 @@ test "absFloat" { | ... | @@ -1693,7 +1684,6 @@ test "absFloat" { |
| 1693 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1684 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1694 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1685 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1695 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1686 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1696 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1697 | 1687 | ||
| 1698 | try testAbsFloat(); | 1688 | try testAbsFloat(); |
| 1699 | try comptime testAbsFloat(); | 1689 | try comptime testAbsFloat(); |
test/behavior/maximum_minimum.zig-5| ... | @@ -31,7 +31,6 @@ test "@max on vectors" { | ... | @@ -31,7 +31,6 @@ test "@max on vectors" { |
| 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 32 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 32 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 33 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 33 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 34 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 35 | if (builtin.zig_backend == .stage2_x86_64 and | 34 | if (builtin.zig_backend == .stage2_x86_64 and |
| 36 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | 35 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; |
| 37 | 36 | ||
| ... | @@ -86,7 +85,6 @@ test "@min for vectors" { | ... | @@ -86,7 +85,6 @@ test "@min for vectors" { |
| 86 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 85 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 87 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 86 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 88 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 87 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 89 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 90 | if (builtin.zig_backend == .stage2_x86_64 and | 88 | if (builtin.zig_backend == .stage2_x86_64 and |
| 91 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | 89 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; |
| 92 | 90 | ||
| ... | @@ -199,7 +197,6 @@ test "@min/@max notices vector bounds" { | ... | @@ -199,7 +197,6 @@ test "@min/@max notices vector bounds" { |
| 199 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 197 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 200 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 198 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 201 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 199 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 202 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 203 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 200 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 204 | 201 | ||
| 205 | var x: @Vector(2, u16) = .{ 140, 40 }; | 202 | var x: @Vector(2, u16) = .{ 140, 40 }; |
| ... | @@ -253,7 +250,6 @@ test "@min/@max notices bounds from vector types" { | ... | @@ -253,7 +250,6 @@ test "@min/@max notices bounds from vector types" { |
| 253 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 250 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 254 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 251 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 255 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 252 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 256 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 257 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 253 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 258 | 254 | ||
| 259 | var x: @Vector(2, u16) = .{ 30, 67 }; | 255 | var x: @Vector(2, u16) = .{ 30, 67 }; |
| ... | @@ -295,7 +291,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known | ... | @@ -295,7 +291,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known |
| 295 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 291 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 296 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 292 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 297 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 293 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 298 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 299 | if (builtin.zig_backend == .stage2_x86_64 and | 294 | if (builtin.zig_backend == .stage2_x86_64 and |
| 300 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest; | 295 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest; |
| 301 | 296 |
test/behavior/muladd.zig-5| ... | @@ -10,7 +10,6 @@ test "@mulAdd" { | ... | @@ -10,7 +10,6 @@ test "@mulAdd" { |
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 13 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 14 | 13 | ||
| 15 | try comptime testMulAdd(); | 14 | try comptime testMulAdd(); |
| 16 | try testMulAdd(); | 15 | try testMulAdd(); |
| ... | @@ -37,7 +36,6 @@ test "@mulAdd f16" { | ... | @@ -37,7 +36,6 @@ test "@mulAdd f16" { |
| 37 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 36 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 38 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 37 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 39 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 38 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 40 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 41 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 39 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 42 | 40 | ||
| 43 | try comptime testMulAdd16(); | 41 | try comptime testMulAdd16(); |
| ... | @@ -111,7 +109,6 @@ test "vector f16" { | ... | @@ -111,7 +109,6 @@ test "vector f16" { |
| 111 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 109 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 112 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 110 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 113 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 111 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 114 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 115 | 112 | ||
| 116 | try comptime vector16(); | 113 | try comptime vector16(); |
| 117 | try vector16(); | 114 | try vector16(); |
| ... | @@ -136,7 +133,6 @@ test "vector f32" { | ... | @@ -136,7 +133,6 @@ test "vector f32" { |
| 136 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 133 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 137 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 134 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 138 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 135 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 139 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 140 | 136 | ||
| 141 | try comptime vector32(); | 137 | try comptime vector32(); |
| 142 | try vector32(); | 138 | try vector32(); |
| ... | @@ -161,7 +157,6 @@ test "vector f64" { | ... | @@ -161,7 +157,6 @@ test "vector f64" { |
| 161 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 157 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 162 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 158 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 163 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 159 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 164 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 165 | 160 | ||
| 166 | try comptime vector64(); | 161 | try comptime vector64(); |
| 167 | try vector64(); | 162 | try vector64(); |
test/behavior/namespace_depends_on_compile_var.zig+2| ... | @@ -3,6 +3,8 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,8 @@ 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_spirv64) return error.SkipZigTest; | ||
| 7 | |||
| 6 | if (some_namespace.a_bool) { | 8 | if (some_namespace.a_bool) { |
| 7 | try expect(some_namespace.a_bool); | 9 | try expect(some_namespace.a_bool); |
| 8 | } else { | 10 | } else { |
test/behavior/null.zig-2| ... | @@ -32,7 +32,6 @@ test "test maybe object and get a pointer to the inner value" { | ... | @@ -32,7 +32,6 @@ test "test maybe object and get a pointer to the inner value" { |
| 32 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 32 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 33 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 33 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 34 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 34 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 35 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 36 | 35 | ||
| 37 | var maybe_bool: ?bool = true; | 36 | var maybe_bool: ?bool = true; |
| 38 | 37 | ||
| ... | @@ -142,7 +141,6 @@ test "if var maybe pointer" { | ... | @@ -142,7 +141,6 @@ test "if var maybe pointer" { |
| 142 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 141 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 143 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 142 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 144 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 143 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 145 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 146 | 144 | ||
| 147 | try expect(shouldBeAPlus1(Particle{ | 145 | try expect(shouldBeAPlus1(Particle{ |
| 148 | .a = 14, | 146 | .a = 14, |
test/behavior/optional.zig+1-3| ... | @@ -72,7 +72,6 @@ test "address of unwrap optional" { | ... | @@ -72,7 +72,6 @@ test "address of unwrap optional" { |
| 72 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 72 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 73 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 73 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 74 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 74 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 75 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 76 | 75 | ||
| 77 | const S = struct { | 76 | const S = struct { |
| 78 | const Foo = struct { | 77 | const Foo = struct { |
| ... | @@ -341,7 +340,6 @@ test "optional pointer to zero bit optional payload" { | ... | @@ -341,7 +340,6 @@ test "optional pointer to zero bit optional payload" { |
| 341 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 340 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 342 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 341 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 343 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 342 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 344 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 345 | 343 | ||
| 346 | const B = struct { | 344 | const B = struct { |
| 347 | fn foo(_: *@This()) void {} | 345 | fn foo(_: *@This()) void {} |
| ... | @@ -453,6 +451,7 @@ test "Optional slice passed to function" { | ... | @@ -453,6 +451,7 @@ test "Optional slice passed to function" { |
| 453 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 451 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 454 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 452 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 455 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 453 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 454 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 456 | 455 | ||
| 457 | const S = struct { | 456 | const S = struct { |
| 458 | fn foo(a: ?[]const u8) !void { | 457 | fn foo(a: ?[]const u8) !void { |
| ... | @@ -518,7 +517,6 @@ test "copied optional doesn't alias source" { | ... | @@ -518,7 +517,6 @@ test "copied optional doesn't alias source" { |
| 518 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 517 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 519 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 518 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 520 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 519 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 521 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 522 | 520 | ||
| 523 | var opt_x: ?[3]f32 = [_]f32{0.0} ** 3; | 521 | var opt_x: ?[3]f32 = [_]f32{0.0} ** 3; |
| 524 | 522 |
test/behavior/pub_enum.zig+4| ... | @@ -3,6 +3,8 @@ const other = @import("pub_enum/other.zig"); | ... | @@ -3,6 +3,8 @@ 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_spirv64) return error.SkipZigTest; | ||
| 7 | |||
| 6 | try pubEnumTest(other.APubEnum.Two); | 8 | try pubEnumTest(other.APubEnum.Two); |
| 7 | } | 9 | } |
| 8 | fn pubEnumTest(foo: other.APubEnum) !void { | 10 | fn pubEnumTest(foo: other.APubEnum) !void { |
| ... | @@ -10,5 +12,7 @@ fn pubEnumTest(foo: other.APubEnum) !void { | ... | @@ -10,5 +12,7 @@ fn pubEnumTest(foo: other.APubEnum) !void { |
| 10 | } | 12 | } |
| 11 | 13 | ||
| 12 | test "cast with imported symbol" { | 14 | test "cast with imported symbol" { |
| 15 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 16 | |||
| 13 | try expect(@as(other.size_t, 42) == 42); | 17 | try expect(@as(other.size_t, 42) == 42); |
| 14 | } | 18 | } |
test/behavior/shuffle.zig-3| ... | @@ -8,7 +8,6 @@ test "@shuffle int" { | ... | @@ -8,7 +8,6 @@ test "@shuffle int" { |
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 12 | 11 | ||
| 13 | const S = struct { | 12 | const S = struct { |
| 14 | fn doTheTest() !void { | 13 | fn doTheTest() !void { |
| ... | @@ -54,7 +53,6 @@ test "@shuffle bool 1" { | ... | @@ -54,7 +53,6 @@ test "@shuffle bool 1" { |
| 54 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 53 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 55 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 54 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 56 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 55 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 57 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 58 | 56 | ||
| 59 | const S = struct { | 57 | const S = struct { |
| 60 | fn doTheTest() !void { | 58 | fn doTheTest() !void { |
| ... | @@ -77,7 +75,6 @@ test "@shuffle bool 2" { | ... | @@ -77,7 +75,6 @@ test "@shuffle bool 2" { |
| 77 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 75 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 78 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 76 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 79 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 77 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 80 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 81 | 78 | ||
| 82 | if (builtin.zig_backend == .stage2_llvm) { | 79 | if (builtin.zig_backend == .stage2_llvm) { |
| 83 | // https://github.com/ziglang/zig/issues/3246 | 80 | // https://github.com/ziglang/zig/issues/3246 |
test/behavior/slice_sentinel_comptime.zig+2| ... | @@ -1,3 +1,5 @@ | ... | @@ -1,3 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 2 | |||
| 1 | test "comptime slice-sentinel in bounds (unterminated)" { | 3 | test "comptime slice-sentinel in bounds (unterminated)" { |
| 2 | // array | 4 | // array |
| 3 | comptime { | 5 | comptime { |
test/behavior/struct.zig+2-2| ... | @@ -1744,8 +1744,6 @@ test "struct init with no result pointer sets field result types" { | ... | @@ -1744,8 +1744,6 @@ test "struct init with no result pointer sets field result types" { |
| 1744 | } | 1744 | } |
| 1745 | 1745 | ||
| 1746 | test "runtime side-effects in comptime-known struct init" { | 1746 | test "runtime side-effects in comptime-known struct init" { |
| 1747 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1748 | |||
| 1749 | var side_effects: u4 = 0; | 1747 | var side_effects: u4 = 0; |
| 1750 | const S = struct { a: u4, b: u4, c: u4, d: u4 }; | 1748 | const S = struct { a: u4, b: u4, c: u4, d: u4 }; |
| 1751 | const init = S{ | 1749 | const init = S{ |
| ... | @@ -2056,6 +2054,8 @@ test "struct field default value is a call" { | ... | @@ -2056,6 +2054,8 @@ test "struct field default value is a call" { |
| 2056 | } | 2054 | } |
| 2057 | 2055 | ||
| 2058 | test "aggregate initializers should allow initializing comptime fields, verifying equality" { | 2056 | test "aggregate initializers should allow initializing comptime fields, verifying equality" { |
| 2057 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2058 | |||
| 2059 | var x: u32 = 15; | 2059 | var x: u32 = 15; |
| 2060 | _ = &x; | 2060 | _ = &x; |
| 2061 | const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x }); | 2061 | const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x }); |
test/behavior/switch_on_captured_error.zig+4| ... | @@ -5,6 +5,8 @@ const expectError = std.testing.expectError; | ... | @@ -5,6 +5,8 @@ const expectError = std.testing.expectError; |
| 5 | const expectEqual = std.testing.expectEqual; | 5 | const expectEqual = std.testing.expectEqual; |
| 6 | 6 | ||
| 7 | test "switch on error union catch capture" { | 7 | test "switch on error union catch capture" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 8 | const S = struct { | 10 | const S = struct { |
| 9 | const Error = error{ A, B, C }; | 11 | const Error = error{ A, B, C }; |
| 10 | fn doTheTest() !void { | 12 | fn doTheTest() !void { |
| ... | @@ -257,6 +259,8 @@ test "switch on error union catch capture" { | ... | @@ -257,6 +259,8 @@ test "switch on error union catch capture" { |
| 257 | } | 259 | } |
| 258 | 260 | ||
| 259 | test "switch on error union if else capture" { | 261 | test "switch on error union if else capture" { |
| 262 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 263 | |||
| 260 | const S = struct { | 264 | const S = struct { |
| 261 | const Error = error{ A, B, C }; | 265 | const Error = error{ A, B, C }; |
| 262 | fn doTheTest() !void { | 266 | fn doTheTest() !void { |
test/behavior/truncate.zig-1| ... | @@ -69,7 +69,6 @@ test "truncate on vectors" { | ... | @@ -69,7 +69,6 @@ test "truncate on vectors" { |
| 69 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 69 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 70 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 70 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 71 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 71 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 72 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 73 | 72 | ||
| 74 | const S = struct { | 73 | const S = struct { |
| 75 | fn doTheTest() !void { | 74 | fn doTheTest() !void { |
test/behavior/tuple.zig-1| ... | @@ -483,7 +483,6 @@ test "empty tuple type" { | ... | @@ -483,7 +483,6 @@ test "empty tuple type" { |
| 483 | 483 | ||
| 484 | test "tuple with comptime fields with non empty initializer" { | 484 | test "tuple with comptime fields with non empty initializer" { |
| 485 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 485 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 486 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 487 | 486 | ||
| 488 | const a: struct { comptime comptime_int = 0 } = .{0}; | 487 | const a: struct { comptime comptime_int = 0 } = .{0}; |
| 489 | _ = a; | 488 | _ = a; |
test/behavior/union.zig+2-1| ... | @@ -1119,6 +1119,7 @@ test "@unionInit on union with tag but no fields" { | ... | @@ -1119,6 +1119,7 @@ test "@unionInit on union with tag but no fields" { |
| 1119 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1119 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1121 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1121 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1122 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1122 | 1123 | ||
| 1123 | const S = struct { | 1124 | const S = struct { |
| 1124 | const Type = enum(u8) { no_op = 105 }; | 1125 | const Type = enum(u8) { no_op = 105 }; |
| ... | @@ -2059,7 +2060,6 @@ test "store of comptime reinterpreted memory to packed union" { | ... | @@ -2059,7 +2060,6 @@ test "store of comptime reinterpreted memory to packed union" { |
| 2059 | 2060 | ||
| 2060 | test "union field is a pointer to an aligned version of itself" { | 2061 | test "union field is a pointer to an aligned version of itself" { |
| 2061 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2062 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2062 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2063 | 2063 | ||
| 2064 | const E = union { | 2064 | const E = union { |
| 2065 | next: *align(1) @This(), | 2065 | next: *align(1) @This(), |
| ... | @@ -2181,6 +2181,7 @@ test "create union(enum) from other union(enum)" { | ... | @@ -2181,6 +2181,7 @@ test "create union(enum) from other union(enum)" { |
| 2181 | if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO | 2181 | if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO |
| 2182 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2182 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2183 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2183 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2184 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 2184 | 2185 | ||
| 2185 | const string = "hello world"; | 2186 | const string = "hello world"; |
| 2186 | const TempRef = struct { | 2187 | const TempRef = struct { |
test/behavior/vector.zig-15| ... | @@ -179,7 +179,6 @@ test "array vector coercion - odd sizes" { | ... | @@ -179,7 +179,6 @@ test "array vector coercion - odd sizes" { |
| 179 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 179 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 180 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 180 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 181 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 181 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 182 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 183 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 182 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 184 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 183 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 185 | 184 | ||
| ... | @@ -219,7 +218,6 @@ test "array to vector with element type coercion" { | ... | @@ -219,7 +218,6 @@ test "array to vector with element type coercion" { |
| 219 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 218 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 220 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 219 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 221 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 220 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 222 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 223 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 221 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 224 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; | 222 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; |
| 225 | 223 | ||
| ... | @@ -261,7 +259,6 @@ test "tuple to vector" { | ... | @@ -261,7 +259,6 @@ test "tuple to vector" { |
| 261 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 259 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 262 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 260 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 263 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 261 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 264 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 265 | 262 | ||
| 266 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { | 263 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { |
| 267 | // Regressed with LLVM 14: | 264 | // Regressed with LLVM 14: |
| ... | @@ -329,7 +326,6 @@ test "vector @splat" { | ... | @@ -329,7 +326,6 @@ test "vector @splat" { |
| 329 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 326 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 330 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 327 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 331 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 328 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 332 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 333 | 329 | ||
| 334 | if (builtin.zig_backend == .stage2_llvm and | 330 | if (builtin.zig_backend == .stage2_llvm and |
| 335 | builtin.os.tag == .macos) | 331 | builtin.os.tag == .macos) |
| ... | @@ -628,7 +624,6 @@ test "vector bitwise not operator" { | ... | @@ -628,7 +624,6 @@ test "vector bitwise not operator" { |
| 628 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 629 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 630 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 631 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 632 | 627 | ||
| 633 | const S = struct { | 628 | const S = struct { |
| 634 | fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void { | 629 | fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void { |
| ... | @@ -660,7 +655,6 @@ test "vector shift operators" { | ... | @@ -660,7 +655,6 @@ test "vector shift operators" { |
| 660 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 655 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 661 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 656 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 662 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 657 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 663 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 664 | 658 | ||
| 665 | const S = struct { | 659 | const S = struct { |
| 666 | fn doTheTestShift(x: anytype, y: anytype) !void { | 660 | fn doTheTestShift(x: anytype, y: anytype) !void { |
| ... | @@ -915,7 +909,6 @@ test "mask parameter of @shuffle is comptime scope" { | ... | @@ -915,7 +909,6 @@ test "mask parameter of @shuffle is comptime scope" { |
| 915 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 909 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 916 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 910 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 917 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 911 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 918 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 919 | 912 | ||
| 920 | const __v4hi = @Vector(4, i16); | 913 | const __v4hi = @Vector(4, i16); |
| 921 | var v4_a = __v4hi{ 0, 0, 0, 0 }; | 914 | var v4_a = __v4hi{ 0, 0, 0, 0 }; |
| ... | @@ -1067,7 +1060,6 @@ test "@addWithOverflow" { | ... | @@ -1067,7 +1060,6 @@ test "@addWithOverflow" { |
| 1067 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1060 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1068 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1061 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1069 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1062 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1070 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1071 | 1063 | ||
| 1072 | const S = struct { | 1064 | const S = struct { |
| 1073 | fn doTheTest() !void { | 1065 | fn doTheTest() !void { |
| ... | @@ -1115,7 +1107,6 @@ test "@subWithOverflow" { | ... | @@ -1115,7 +1107,6 @@ test "@subWithOverflow" { |
| 1115 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1107 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1116 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1108 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1117 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1109 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1118 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1119 | 1110 | ||
| 1120 | const S = struct { | 1111 | const S = struct { |
| 1121 | fn doTheTest() !void { | 1112 | fn doTheTest() !void { |
| ... | @@ -1169,7 +1160,6 @@ test "@shlWithOverflow" { | ... | @@ -1169,7 +1160,6 @@ test "@shlWithOverflow" { |
| 1169 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1160 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1170 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1161 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1171 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1162 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1172 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1173 | 1163 | ||
| 1174 | const S = struct { | 1164 | const S = struct { |
| 1175 | fn doTheTest() !void { | 1165 | fn doTheTest() !void { |
| ... | @@ -1236,7 +1226,6 @@ test "byte vector initialized in inline function" { | ... | @@ -1236,7 +1226,6 @@ test "byte vector initialized in inline function" { |
| 1236 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1226 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1237 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1227 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1238 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1228 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1239 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1240 | 1229 | ||
| 1241 | if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and | 1230 | if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and |
| 1242 | builtin.cpu.features.isEnabled(@intFromEnum(std.Target.x86.Feature.avx512f))) | 1231 | builtin.cpu.features.isEnabled(@intFromEnum(std.Target.x86.Feature.avx512f))) |
| ... | @@ -1306,7 +1295,6 @@ test "@intCast to u0" { | ... | @@ -1306,7 +1295,6 @@ test "@intCast to u0" { |
| 1306 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1295 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1307 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1296 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1308 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1297 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1309 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1310 | 1298 | ||
| 1311 | var zeros = @Vector(2, u32){ 0, 0 }; | 1299 | var zeros = @Vector(2, u32){ 0, 0 }; |
| 1312 | _ = &zeros; | 1300 | _ = &zeros; |
| ... | @@ -1331,7 +1319,6 @@ test "array operands to shuffle are coerced to vectors" { | ... | @@ -1331,7 +1319,6 @@ test "array operands to shuffle are coerced to vectors" { |
| 1331 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1319 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1332 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1320 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1333 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1321 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1334 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1335 | 1322 | ||
| 1336 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; | 1323 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; |
| 1337 | 1324 | ||
| ... | @@ -1357,7 +1344,6 @@ test "store packed vector element" { | ... | @@ -1357,7 +1344,6 @@ test "store packed vector element" { |
| 1357 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1344 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1358 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1345 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1359 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1346 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1360 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1361 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1347 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1362 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1348 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1363 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1349 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| ... | @@ -1454,7 +1440,6 @@ test "compare vectors with different element types" { | ... | @@ -1454,7 +1440,6 @@ test "compare vectors with different element types" { |
| 1454 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1440 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1455 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1441 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 1456 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1442 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1457 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | ||
| 1458 | 1443 | ||
| 1459 | var a: @Vector(2, u8) = .{ 1, 2 }; | 1444 | var a: @Vector(2, u8) = .{ 1, 2 }; |
| 1460 | var b: @Vector(2, u9) = .{ 3, 0 }; | 1445 | var b: @Vector(2, u9) = .{ 3, 0 }; |
test/behavior/wrapping_arithmetic.zig+6| ... | @@ -5,6 +5,8 @@ const maxInt = std.math.maxInt; | ... | @@ -5,6 +5,8 @@ const maxInt = std.math.maxInt; |
| 5 | const expect = std.testing.expect; | 5 | const expect = std.testing.expect; |
| 6 | 6 | ||
| 7 | test "wrapping add" { | 7 | test "wrapping add" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 8 | const S = struct { | 10 | const S = struct { |
| 9 | fn doTheTest() !void { | 11 | fn doTheTest() !void { |
| 10 | try testWrapAdd(i8, -3, 10, 7); | 12 | try testWrapAdd(i8, -3, 10, 7); |
| ... | @@ -40,6 +42,8 @@ test "wrapping add" { | ... | @@ -40,6 +42,8 @@ test "wrapping add" { |
| 40 | } | 42 | } |
| 41 | 43 | ||
| 42 | test "wrapping subtraction" { | 44 | test "wrapping subtraction" { |
| 45 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 46 | |||
| 43 | const S = struct { | 47 | const S = struct { |
| 44 | fn doTheTest() !void { | 48 | fn doTheTest() !void { |
| 45 | try testWrapSub(i8, -3, 10, -13); | 49 | try testWrapSub(i8, -3, 10, -13); |
| ... | @@ -73,6 +77,8 @@ test "wrapping subtraction" { | ... | @@ -73,6 +77,8 @@ test "wrapping subtraction" { |
| 73 | } | 77 | } |
| 74 | 78 | ||
| 75 | test "wrapping multiplication" { | 79 | test "wrapping multiplication" { |
| 80 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 81 | |||
| 76 | // TODO: once #9660 has been solved, remove this line | 82 | // TODO: once #9660 has been solved, remove this line |
| 77 | if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; | 83 | if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; |
| 78 | 84 |