| author | |
| committer | |
| log | 7621e56938ed6d86827c11ee6272db722f350fed |
| tree | af79c9d211810cd7ea6d3a145fa0e4f08bc85b92 |
| parent | 413ef3aa38899195d113fc51a5c035a7c15103eb |
| parent | c92cc5798f0ea72ab1c77ae12c6124e5ab090730 |
| signature |
spirv: make more tests pass44 files changed, 537 insertions(+), 437 deletions(-)
src/codegen/spirv.zig+511-307| ... | @@ -242,7 +242,7 @@ pub const DeclGen = struct { | ... | @@ -242,7 +242,7 @@ pub const DeclGen = struct { |
| 242 | return self.spv.declPtr(spv_decl_index).result_id; | 242 | return self.spv.declPtr(spv_decl_index).result_id; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | return try self.constant(ty, val); | 245 | return try self.constant(ty, val, .direct); |
| 246 | } | 246 | } |
| 247 | const index = Air.refToIndex(inst).?; | 247 | const index = Air.refToIndex(inst).?; |
| 248 | return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. | 248 | return self.inst_results.get(index).?; // Assertion means instruction does not dominate usage. |
| ... | @@ -369,21 +369,11 @@ pub const DeclGen = struct { | ... | @@ -369,21 +369,11 @@ pub const DeclGen = struct { |
| 369 | .composite_integer, | 369 | .composite_integer, |
| 370 | }; | 370 | }; |
| 371 | }, | 371 | }, |
| 372 | .Enum => blk: { | ||
| 373 | var buffer: Type.Payload.Bits = undefined; | ||
| 374 | const int_ty = ty.intTagType(&buffer); | ||
| 375 | const int_info = int_ty.intInfo(target); | ||
| 376 | break :blk ArithmeticTypeInfo{ | ||
| 377 | .bits = int_info.bits, | ||
| 378 | .is_vector = false, | ||
| 379 | .signedness = int_info.signedness, | ||
| 380 | .class = .integer, | ||
| 381 | }; | ||
| 382 | }, | ||
| 383 | // As of yet, there is no vector support in the self-hosted compiler. | 372 | // As of yet, there is no vector support in the self-hosted compiler. |
| 384 | .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), | 373 | .Vector => self.todo("implement arithmeticTypeInfo for Vector", .{}), |
| 385 | // TODO: For which types is this the case? | 374 | // TODO: For which types is this the case? |
| 386 | else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), | 375 | // else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), |
| 376 | else => unreachable, | ||
| 387 | }; | 377 | }; |
| 388 | } | 378 | } |
| 389 | 379 | ||
| ... | @@ -452,6 +442,37 @@ pub const DeclGen = struct { | ... | @@ -452,6 +442,37 @@ pub const DeclGen = struct { |
| 452 | } | 442 | } |
| 453 | } | 443 | } |
| 454 | 444 | ||
| 445 | /// Construct a struct at runtime. | ||
| 446 | /// result_ty_ref must be a struct type. | ||
| 447 | fn constructStruct(self: *DeclGen, result_ty_ref: SpvType.Ref, constituents: []const IdRef) !IdRef { | ||
| 448 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' | ||
| 449 | // operands are not constant. | ||
| 450 | // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 | ||
| 451 | // For now, just initialize the struct by setting the fields manually... | ||
| 452 | // TODO: Make this OpCompositeConstruct when we can | ||
| 453 | const ptr_composite_id = try self.alloc(result_ty_ref, null); | ||
| 454 | // Note: using 32-bit ints here because usize crashes the translator as well | ||
| 455 | const index_ty_ref = try self.intType(.unsigned, 32); | ||
| 456 | const spv_composite_ty = self.spv.typeRefType(result_ty_ref); | ||
| 457 | const members = spv_composite_ty.payload(.@"struct").members; | ||
| 458 | for (constituents, members, 0..) |constitent_id, member, index| { | ||
| 459 | const index_id = try self.constInt(index_ty_ref, index); | ||
| 460 | const ptr_member_ty_ref = try self.spv.ptrType(member.ty, .Generic, 0); | ||
| 461 | const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id}); | ||
| 462 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | ||
| 463 | .pointer = ptr_id, | ||
| 464 | .object = constitent_id, | ||
| 465 | }); | ||
| 466 | } | ||
| 467 | const result_id = self.spv.allocId(); | ||
| 468 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ | ||
| 469 | .id_result_type = self.typeId(result_ty_ref), | ||
| 470 | .id_result = result_id, | ||
| 471 | .pointer = ptr_composite_id, | ||
| 472 | }); | ||
| 473 | return result_id; | ||
| 474 | } | ||
| 475 | |||
| 455 | const IndirectConstantLowering = struct { | 476 | const IndirectConstantLowering = struct { |
| 456 | const undef = 0xAA; | 477 | const undef = 0xAA; |
| 457 | 478 | ||
| ... | @@ -705,6 +726,10 @@ pub const DeclGen = struct { | ... | @@ -705,6 +726,10 @@ pub const DeclGen = struct { |
| 705 | try self.lower(ptr_ty, slice.ptr); | 726 | try self.lower(ptr_ty, slice.ptr); |
| 706 | try self.addInt(Type.usize, slice.len); | 727 | try self.addInt(Type.usize, slice.len); |
| 707 | }, | 728 | }, |
| 729 | .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)), | ||
| 730 | .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => { | ||
| 731 | try self.addInt(Type.usize, val); | ||
| 732 | }, | ||
| 708 | else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}), | 733 | else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}), |
| 709 | }, | 734 | }, |
| 710 | .Struct => { | 735 | .Struct => { |
| ... | @@ -996,14 +1021,16 @@ pub const DeclGen = struct { | ... | @@ -996,14 +1021,16 @@ pub const DeclGen = struct { |
| 996 | /// the constant is more complicated however, it needs to be lowered to an indirect constant, which | 1021 | /// the constant is more complicated however, it needs to be lowered to an indirect constant, which |
| 997 | /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default. | 1022 | /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default. |
| 998 | /// This function should only be called during function code generation. | 1023 | /// This function should only be called during function code generation. |
| 999 | fn constant(self: *DeclGen, ty: Type, val: Value) !IdRef { | 1024 | fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { |
| 1000 | const target = self.getTarget(); | 1025 | const target = self.getTarget(); |
| 1001 | const section = &self.spv.sections.types_globals_constants; | 1026 | const section = &self.spv.sections.types_globals_constants; |
| 1002 | const result_ty_ref = try self.resolveType(ty, .direct); | 1027 | const result_ty_ref = try self.resolveType(ty, repr); |
| 1003 | const result_ty_id = self.typeId(result_ty_ref); | 1028 | const result_ty_id = self.typeId(result_ty_ref); |
| 1004 | const result_id = self.spv.allocId(); | 1029 | |
| 1030 | log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) }); | ||
| 1005 | 1031 | ||
| 1006 | if (val.isUndef()) { | 1032 | if (val.isUndef()) { |
| 1033 | const result_id = self.spv.allocId(); | ||
| 1007 | try section.emit(self.spv.gpa, .OpUndef, .{ | 1034 | try section.emit(self.spv.gpa, .OpUndef, .{ |
| 1008 | .id_result_type = result_ty_id, | 1035 | .id_result_type = result_ty_id, |
| 1009 | .id_result = result_id, | 1036 | .id_result = result_id, |
| ... | @@ -1014,24 +1041,76 @@ pub const DeclGen = struct { | ... | @@ -1014,24 +1041,76 @@ pub const DeclGen = struct { |
| 1014 | switch (ty.zigTypeTag()) { | 1041 | switch (ty.zigTypeTag()) { |
| 1015 | .Int => { | 1042 | .Int => { |
| 1016 | if (ty.isSignedInt()) { | 1043 | if (ty.isSignedInt()) { |
| 1017 | try self.genConstInt(result_ty_ref, result_id, val.toSignedInt(target)); | 1044 | return try self.constInt(result_ty_ref, val.toSignedInt(target)); |
| 1018 | } else { | 1045 | } else { |
| 1019 | try self.genConstInt(result_ty_ref, result_id, val.toUnsignedInt(target)); | 1046 | return try self.constInt(result_ty_ref, val.toUnsignedInt(target)); |
| 1020 | } | 1047 | } |
| 1021 | }, | 1048 | }, |
| 1022 | .Bool => { | 1049 | .Bool => switch (repr) { |
| 1023 | const operands = .{ .id_result_type = result_ty_id, .id_result = result_id }; | 1050 | .direct => { |
| 1024 | if (val.toBool()) { | 1051 | const result_id = self.spv.allocId(); |
| 1025 | try section.emit(self.spv.gpa, .OpConstantTrue, operands); | 1052 | const operands = .{ .id_result_type = result_ty_id, .id_result = result_id }; |
| 1053 | if (val.toBool()) { | ||
| 1054 | try section.emit(self.spv.gpa, .OpConstantTrue, operands); | ||
| 1055 | } else { | ||
| 1056 | try section.emit(self.spv.gpa, .OpConstantFalse, operands); | ||
| 1057 | } | ||
| 1058 | return result_id; | ||
| 1059 | }, | ||
| 1060 | .indirect => return try self.constInt(result_ty_ref, @boolToInt(val.toBool())), | ||
| 1061 | }, | ||
| 1062 | .Float => { | ||
| 1063 | const result_id = self.spv.allocId(); | ||
| 1064 | switch (ty.floatBits(target)) { | ||
| 1065 | 16 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float32 = val.toFloat(f16) }), | ||
| 1066 | 32 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float32 = val.toFloat(f32) }), | ||
| 1067 | 64 => try self.spv.emitConstant(result_ty_id, result_id, .{ .float64 = val.toFloat(f64) }), | ||
| 1068 | 80, 128 => unreachable, // TODO | ||
| 1069 | else => unreachable, | ||
| 1070 | } | ||
| 1071 | return result_id; | ||
| 1072 | }, | ||
| 1073 | .ErrorSet => { | ||
| 1074 | const value = switch (val.tag()) { | ||
| 1075 | .@"error" => blk: { | ||
| 1076 | const err_name = val.castTag(.@"error").?.data.name; | ||
| 1077 | const kv = try self.module.getErrorValue(err_name); | ||
| 1078 | break :blk @intCast(u16, kv.value); | ||
| 1079 | }, | ||
| 1080 | .zero => 0, | ||
| 1081 | else => unreachable, | ||
| 1082 | }; | ||
| 1083 | |||
| 1084 | return try self.constInt(result_ty_ref, value); | ||
| 1085 | }, | ||
| 1086 | .ErrorUnion => { | ||
| 1087 | const payload_ty = ty.errorUnionPayload(); | ||
| 1088 | const is_pl = val.errorUnionIsPayload(); | ||
| 1089 | const error_val = if (!is_pl) val else Value.initTag(.zero); | ||
| 1090 | |||
| 1091 | const eu_layout = self.errorUnionLayout(payload_ty); | ||
| 1092 | if (!eu_layout.payload_has_bits) { | ||
| 1093 | return try self.constant(Type.anyerror, error_val, repr); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); | ||
| 1097 | |||
| 1098 | var members: [2]IdRef = undefined; | ||
| 1099 | if (eu_layout.error_first) { | ||
| 1100 | members[0] = try self.constant(Type.anyerror, error_val, .indirect); | ||
| 1101 | members[1] = try self.constant(payload_ty, payload_val, .indirect); | ||
| 1026 | } else { | 1102 | } else { |
| 1027 | try section.emit(self.spv.gpa, .OpConstantFalse, operands); | 1103 | members[0] = try self.constant(payload_ty, payload_val, .indirect); |
| 1104 | members[1] = try self.constant(Type.anyerror, error_val, .indirect); | ||
| 1028 | } | 1105 | } |
| 1106 | return try self.spv.constComposite(result_ty_ref, &members); | ||
| 1029 | }, | 1107 | }, |
| 1030 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra | 1108 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra |
| 1031 | // OpVariable that is not really required. | 1109 | // OpVariable that is not really required. |
| 1032 | else => { | 1110 | else => { |
| 1033 | // The value cannot be generated directly, so generate it as an indirect constant, | 1111 | // The value cannot be generated directly, so generate it as an indirect constant, |
| 1034 | // and then perform an OpLoad. | 1112 | // and then perform an OpLoad. |
| 1113 | const result_id = self.spv.allocId(); | ||
| 1035 | const alignment = ty.abiAlignment(target); | 1114 | const alignment = ty.abiAlignment(target); |
| 1036 | const spv_decl_index = try self.spv.allocDecl(.global); | 1115 | const spv_decl_index = try self.spv.allocDecl(.global); |
| 1037 | 1116 | ||
| ... | @@ -1053,10 +1132,9 @@ pub const DeclGen = struct { | ... | @@ -1053,10 +1132,9 @@ pub const DeclGen = struct { |
| 1053 | }); | 1132 | }); |
| 1054 | // TODO: Convert bools? This logic should hook into `load`. It should be a dead | 1133 | // TODO: Convert bools? This logic should hook into `load`. It should be a dead |
| 1055 | // path though considering .Bool is handled above. | 1134 | // path though considering .Bool is handled above. |
| 1135 | return result_id; | ||
| 1056 | }, | 1136 | }, |
| 1057 | } | 1137 | } |
| 1058 | |||
| 1059 | return result_id; | ||
| 1060 | } | 1138 | } |
| 1061 | 1139 | ||
| 1062 | /// Turn a Zig type into a SPIR-V Type, and return its type result-id. | 1140 | /// Turn a Zig type into a SPIR-V Type, and return its type result-id. |
| ... | @@ -1592,10 +1670,23 @@ pub const DeclGen = struct { | ... | @@ -1592,10 +1670,23 @@ pub const DeclGen = struct { |
| 1592 | } | 1670 | } |
| 1593 | } | 1671 | } |
| 1594 | 1672 | ||
| 1673 | fn boolToInt(self: *DeclGen, result_ty_ref: SpvType.Ref, condition_id: IdRef) !IdRef { | ||
| 1674 | const zero_id = try self.constInt(result_ty_ref, 0); | ||
| 1675 | const one_id = try self.constInt(result_ty_ref, 1); | ||
| 1676 | const result_id = self.spv.allocId(); | ||
| 1677 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | ||
| 1678 | .id_result_type = self.typeId(result_ty_ref), | ||
| 1679 | .id_result = result_id, | ||
| 1680 | .condition = condition_id, | ||
| 1681 | .object_1 = one_id, | ||
| 1682 | .object_2 = zero_id, | ||
| 1683 | }); | ||
| 1684 | return result_id; | ||
| 1685 | } | ||
| 1686 | |||
| 1595 | /// Convert representation from indirect (in memory) to direct (in 'register') | 1687 | /// Convert representation from indirect (in memory) to direct (in 'register') |
| 1596 | /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). | 1688 | /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct). |
| 1597 | fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { | 1689 | fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef { |
| 1598 | // const direct_ty_ref = try self.resolveType(ty, .direct); | ||
| 1599 | return switch (ty.zigTypeTag()) { | 1690 | return switch (ty.zigTypeTag()) { |
| 1600 | .Bool => blk: { | 1691 | .Bool => blk: { |
| 1601 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); | 1692 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); |
| ... | @@ -1620,17 +1711,7 @@ pub const DeclGen = struct { | ... | @@ -1620,17 +1711,7 @@ pub const DeclGen = struct { |
| 1620 | return switch (ty.zigTypeTag()) { | 1711 | return switch (ty.zigTypeTag()) { |
| 1621 | .Bool => blk: { | 1712 | .Bool => blk: { |
| 1622 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); | 1713 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); |
| 1623 | const zero_id = try self.constInt(indirect_bool_ty_ref, 0); | 1714 | break :blk self.boolToInt(indirect_bool_ty_ref, operand_id); |
| 1624 | const one_id = try self.constInt(indirect_bool_ty_ref, 1); | ||
| 1625 | const result_id = self.spv.allocId(); | ||
| 1626 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | ||
| 1627 | .id_result_type = self.typeId(indirect_bool_ty_ref), | ||
| 1628 | .id_result = result_id, | ||
| 1629 | .condition = operand_id, | ||
| 1630 | .object_1 = one_id, | ||
| 1631 | .object_2 = zero_id, | ||
| 1632 | }); | ||
| 1633 | break :blk result_id; | ||
| 1634 | }, | 1715 | }, |
| 1635 | else => operand_id, | 1716 | else => operand_id, |
| 1636 | }; | 1717 | }; |
| ... | @@ -1714,6 +1795,9 @@ pub const DeclGen = struct { | ... | @@ -1714,6 +1795,9 @@ pub const DeclGen = struct { |
| 1714 | 1795 | ||
| 1715 | .shuffle => try self.airShuffle(inst), | 1796 | .shuffle => try self.airShuffle(inst), |
| 1716 | 1797 | ||
| 1798 | .ptr_add => try self.airPtrAdd(inst), | ||
| 1799 | .ptr_sub => try self.airPtrSub(inst), | ||
| 1800 | |||
| 1717 | .bit_and => try self.airBinOpSimple(inst, .OpBitwiseAnd), | 1801 | .bit_and => try self.airBinOpSimple(inst, .OpBitwiseAnd), |
| 1718 | .bit_or => try self.airBinOpSimple(inst, .OpBitwiseOr), | 1802 | .bit_or => try self.airBinOpSimple(inst, .OpBitwiseOr), |
| 1719 | .xor => try self.airBinOpSimple(inst, .OpBitwiseXor), | 1803 | .xor => try self.airBinOpSimple(inst, .OpBitwiseXor), |
| ... | @@ -1722,8 +1806,8 @@ pub const DeclGen = struct { | ... | @@ -1722,8 +1806,8 @@ pub const DeclGen = struct { |
| 1722 | 1806 | ||
| 1723 | .shl => try self.airShift(inst, .OpShiftLeftLogical), | 1807 | .shl => try self.airShift(inst, .OpShiftLeftLogical), |
| 1724 | 1808 | ||
| 1725 | .bitcast => try self.airBitcast(inst), | 1809 | .bitcast => try self.airBitCast(inst), |
| 1726 | .intcast, .trunc => try self.airIntcast(inst), | 1810 | .intcast, .trunc => try self.airIntCast(inst), |
| 1727 | .ptrtoint => try self.airPtrToInt(inst), | 1811 | .ptrtoint => try self.airPtrToInt(inst), |
| 1728 | .int_to_float => try self.airIntToFloat(inst), | 1812 | .int_to_float => try self.airIntToFloat(inst), |
| 1729 | .float_to_int => try self.airFloatToInt(inst), | 1813 | .float_to_int => try self.airFloatToInt(inst), |
| ... | @@ -1734,6 +1818,7 @@ pub const DeclGen = struct { | ... | @@ -1734,6 +1818,7 @@ pub const DeclGen = struct { |
| 1734 | .slice_elem_ptr => try self.airSliceElemPtr(inst), | 1818 | .slice_elem_ptr => try self.airSliceElemPtr(inst), |
| 1735 | .slice_elem_val => try self.airSliceElemVal(inst), | 1819 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 1736 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), | 1820 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 1821 | .ptr_elem_val => try self.airPtrElemVal(inst), | ||
| 1737 | 1822 | ||
| 1738 | .get_union_tag => try self.airGetUnionTag(inst), | 1823 | .get_union_tag => try self.airGetUnionTag(inst), |
| 1739 | .struct_field_val => try self.airStructFieldVal(inst), | 1824 | .struct_field_val => try self.airStructFieldVal(inst), |
| ... | @@ -1743,12 +1828,12 @@ pub const DeclGen = struct { | ... | @@ -1743,12 +1828,12 @@ pub const DeclGen = struct { |
| 1743 | .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2), | 1828 | .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2), |
| 1744 | .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3), | 1829 | .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3), |
| 1745 | 1830 | ||
| 1746 | .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual), | 1831 | .cmp_eq => try self.airCmp(inst, .eq), |
| 1747 | .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual), | 1832 | .cmp_neq => try self.airCmp(inst, .neq), |
| 1748 | .cmp_gt => try self.airCmp(inst, .OpFOrdGreaterThan, .OpSGreaterThan, .OpUGreaterThan), | 1833 | .cmp_gt => try self.airCmp(inst, .gt), |
| 1749 | .cmp_gte => try self.airCmp(inst, .OpFOrdGreaterThanEqual, .OpSGreaterThanEqual, .OpUGreaterThanEqual), | 1834 | .cmp_gte => try self.airCmp(inst, .gte), |
| 1750 | .cmp_lt => try self.airCmp(inst, .OpFOrdLessThan, .OpSLessThan, .OpULessThan), | 1835 | .cmp_lt => try self.airCmp(inst, .lt), |
| 1751 | .cmp_lte => try self.airCmp(inst, .OpFOrdLessThanEqual, .OpSLessThanEqual, .OpULessThanEqual), | 1836 | .cmp_lte => try self.airCmp(inst, .lte), |
| 1752 | 1837 | ||
| 1753 | .arg => self.airArg(), | 1838 | .arg => self.airArg(), |
| 1754 | .alloc => try self.airAlloc(inst), | 1839 | .alloc => try self.airAlloc(inst), |
| ... | @@ -1944,64 +2029,83 @@ pub const DeclGen = struct { | ... | @@ -1944,64 +2029,83 @@ pub const DeclGen = struct { |
| 1944 | .float, .bool => unreachable, | 2029 | .float, .bool => unreachable, |
| 1945 | } | 2030 | } |
| 1946 | 2031 | ||
| 1947 | // The operand type must be the same as the result type in SPIR-V. | 2032 | // The operand type must be the same as the result type in SPIR-V, which |
| 2033 | // is the same as in Zig. | ||
| 1948 | const operand_ty_ref = try self.resolveType(operand_ty, .direct); | 2034 | const operand_ty_ref = try self.resolveType(operand_ty, .direct); |
| 1949 | const operand_ty_id = self.typeId(operand_ty_ref); | 2035 | const operand_ty_id = self.typeId(operand_ty_ref); |
| 1950 | 2036 | ||
| 1951 | const op_result_id = blk: { | 2037 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 1952 | // Construct the SPIR-V result type. | ||
| 1953 | // It is almost the same as the zig one, except that the fields must be the same type | ||
| 1954 | // and they must be unsigned. | ||
| 1955 | const overflow_result_ty_ref = try self.spv.simpleStructType(&.{ | ||
| 1956 | .{ .ty = operand_ty_ref, .name = "res" }, | ||
| 1957 | .{ .ty = operand_ty_ref, .name = "ov" }, | ||
| 1958 | }); | ||
| 1959 | const result_id = self.spv.allocId(); | ||
| 1960 | try self.func.body.emit(self.spv.gpa, .OpIAddCarry, .{ | ||
| 1961 | .id_result_type = self.typeId(overflow_result_ty_ref), | ||
| 1962 | .id_result = result_id, | ||
| 1963 | .operand_1 = lhs, | ||
| 1964 | .operand_2 = rhs, | ||
| 1965 | }); | ||
| 1966 | break :blk result_id; | ||
| 1967 | }; | ||
| 1968 | |||
| 1969 | // Now convert the SPIR-V flavor result into a Zig-flavor result. | ||
| 1970 | // First, extract the two fields. | ||
| 1971 | const unsigned_result = try self.extractField(operand_ty, op_result_id, 0); | ||
| 1972 | const overflow = try self.extractField(operand_ty, op_result_id, 1); | ||
| 1973 | |||
| 1974 | // We need to convert the results to the types that Zig expects here. | ||
| 1975 | // The `result` is the same type except unsigned, so we can just bitcast that. | ||
| 1976 | // TODO: This can be removed in Kernels as there are only unsigned ints. Maybe for | ||
| 1977 | // shaders as well? | ||
| 1978 | const result = try self.bitcast(operand_ty_id, unsigned_result); | ||
| 1979 | |||
| 1980 | // The overflow needs to be converted into whatever is used to represent it in Zig. | ||
| 1981 | const casted_overflow = blk: { | ||
| 1982 | const ov_ty = result_ty.tupleFields().types[1]; | ||
| 1983 | const ov_ty_id = try self.resolveTypeId(ov_ty); | ||
| 1984 | const result_id = self.spv.allocId(); | ||
| 1985 | try self.func.body.emit(self.spv.gpa, .OpUConvert, .{ | ||
| 1986 | .id_result_type = ov_ty_id, | ||
| 1987 | .id_result = result_id, | ||
| 1988 | .unsigned_value = overflow, | ||
| 1989 | }); | ||
| 1990 | break :blk result_id; | ||
| 1991 | }; | ||
| 1992 | 2038 | ||
| 1993 | // TODO: If copying this function for borrow, make sure to convert -1 to 1 as appropriate. | 2039 | const ov_ty = result_ty.tupleFields().types[1]; |
| 2040 | // Note: result is stored in a struct, so indirect representation. | ||
| 2041 | const ov_ty_ref = try self.resolveType(ov_ty, .indirect); | ||
| 1994 | 2042 | ||
| 1995 | // Finally, construct the Zig type. | 2043 | // TODO: Operations other than addition. |
| 1996 | // Layout is result, overflow. | 2044 | const value_id = self.spv.allocId(); |
| 1997 | const result_id = self.spv.allocId(); | 2045 | try self.func.body.emit(self.spv.gpa, .OpIAdd, .{ |
| 1998 | const constituents = [_]IdRef{ result, casted_overflow }; | ||
| 1999 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | ||
| 2000 | .id_result_type = operand_ty_id, | 2046 | .id_result_type = operand_ty_id, |
| 2001 | .id_result = result_id, | 2047 | .id_result = value_id, |
| 2002 | .constituents = &constituents, | 2048 | .operand_1 = lhs, |
| 2049 | .operand_2 = rhs, | ||
| 2050 | }); | ||
| 2051 | |||
| 2052 | const overflowed_id = switch (info.signedness) { | ||
| 2053 | .unsigned => blk: { | ||
| 2054 | // Overflow happened if the result is smaller than either of the operands. It doesn't matter which. | ||
| 2055 | const overflowed_id = self.spv.allocId(); | ||
| 2056 | try self.func.body.emit(self.spv.gpa, .OpULessThan, .{ | ||
| 2057 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2058 | .id_result = overflowed_id, | ||
| 2059 | .operand_1 = value_id, | ||
| 2060 | .operand_2 = lhs, | ||
| 2061 | }); | ||
| 2062 | break :blk overflowed_id; | ||
| 2063 | }, | ||
| 2064 | .signed => blk: { | ||
| 2065 | // Overflow happened if: | ||
| 2066 | // - rhs is negative and value > lhs | ||
| 2067 | // - rhs is positive and value < lhs | ||
| 2068 | // This can be shortened to: | ||
| 2069 | // (rhs < 0 && value > lhs) || (rhs >= 0 && value <= lhs) | ||
| 2070 | // = (rhs < 0) == (value > lhs) | ||
| 2071 | // Note that signed overflow is also wrapping in spir-v. | ||
| 2072 | |||
| 2073 | const rhs_lt_zero_id = self.spv.allocId(); | ||
| 2074 | const zero_id = try self.constInt(operand_ty_ref, 0); | ||
| 2075 | try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ | ||
| 2076 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2077 | .id_result = rhs_lt_zero_id, | ||
| 2078 | .operand_1 = rhs, | ||
| 2079 | .operand_2 = zero_id, | ||
| 2080 | }); | ||
| 2081 | |||
| 2082 | const value_gt_lhs_id = self.spv.allocId(); | ||
| 2083 | try self.func.body.emit(self.spv.gpa, .OpSGreaterThan, .{ | ||
| 2084 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2085 | .id_result = value_gt_lhs_id, | ||
| 2086 | .operand_1 = value_id, | ||
| 2087 | .operand_2 = lhs, | ||
| 2088 | }); | ||
| 2089 | |||
| 2090 | const overflowed_id = self.spv.allocId(); | ||
| 2091 | try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{ | ||
| 2092 | .id_result_type = self.typeId(bool_ty_ref), | ||
| 2093 | .id_result = overflowed_id, | ||
| 2094 | .operand_1 = rhs_lt_zero_id, | ||
| 2095 | .operand_2 = value_gt_lhs_id, | ||
| 2096 | }); | ||
| 2097 | break :blk overflowed_id; | ||
| 2098 | }, | ||
| 2099 | }; | ||
| 2100 | |||
| 2101 | // Construct the struct that Zig wants as result. | ||
| 2102 | // The value should already be the correct type. | ||
| 2103 | const ov_id = try self.boolToInt(ov_ty_ref, overflowed_id); | ||
| 2104 | const result_ty_ref = try self.resolveType(result_ty, .direct); | ||
| 2105 | return try self.constructStruct(result_ty_ref, &.{ | ||
| 2106 | value_id, | ||
| 2107 | ov_id, | ||
| 2003 | }); | 2108 | }); |
| 2004 | return result_id; | ||
| 2005 | } | 2109 | } |
| 2006 | 2110 | ||
| 2007 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2111 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -2040,85 +2144,262 @@ pub const DeclGen = struct { | ... | @@ -2040,85 +2144,262 @@ pub const DeclGen = struct { |
| 2040 | return result_id; | 2144 | return result_id; |
| 2041 | } | 2145 | } |
| 2042 | 2146 | ||
| 2043 | fn airCmp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !?IdRef { | 2147 | /// AccessChain is essentially PtrAccessChain with 0 as initial argument. The effective |
| 2044 | if (self.liveness.isUnused(inst)) return null; | 2148 | /// difference lies in whether the resulting type of the first dereference will be the |
| 2045 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2149 | /// same as that of the base pointer, or that of a dereferenced base pointer. AccessChain |
| 2046 | var lhs_id = try self.resolve(bin_op.lhs); | 2150 | /// is the latter and PtrAccessChain is the former. |
| 2047 | var rhs_id = try self.resolve(bin_op.rhs); | 2151 | fn accessChain( |
| 2152 | self: *DeclGen, | ||
| 2153 | result_ty_ref: SpvType.Ref, | ||
| 2154 | base: IdRef, | ||
| 2155 | indexes: []const IdRef, | ||
| 2156 | ) !IdRef { | ||
| 2048 | const result_id = self.spv.allocId(); | 2157 | const result_id = self.spv.allocId(); |
| 2049 | const result_type_id = try self.resolveTypeId(Type.bool); | 2158 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 2050 | const op_ty = self.air.typeOf(bin_op.lhs); | 2159 | .id_result_type = self.typeId(result_ty_ref), |
| 2051 | assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.module)); | 2160 | .id_result = result_id, |
| 2161 | .base = base, | ||
| 2162 | .indexes = indexes, | ||
| 2163 | }); | ||
| 2164 | return result_id; | ||
| 2165 | } | ||
| 2052 | 2166 | ||
| 2053 | // Comparisons are generally applicable to both scalar and vector operations in SPIR-V, | 2167 | fn ptrAccessChain( |
| 2054 | // but int and float versions of operations require different opcodes. | 2168 | self: *DeclGen, |
| 2055 | const info = try self.arithmeticTypeInfo(op_ty); | 2169 | result_ty_ref: SpvType.Ref, |
| 2170 | base: IdRef, | ||
| 2171 | element: IdRef, | ||
| 2172 | indexes: []const IdRef, | ||
| 2173 | ) !IdRef { | ||
| 2174 | const result_id = self.spv.allocId(); | ||
| 2175 | try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ | ||
| 2176 | .id_result_type = self.typeId(result_ty_ref), | ||
| 2177 | .id_result = result_id, | ||
| 2178 | .base = base, | ||
| 2179 | .element = element, | ||
| 2180 | .indexes = indexes, | ||
| 2181 | }); | ||
| 2182 | return result_id; | ||
| 2183 | } | ||
| 2056 | 2184 | ||
| 2057 | const opcode_index: usize = switch (info.class) { | 2185 | fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef { |
| 2058 | .composite_integer => { | 2186 | const result_ty_ref = try self.resolveType(result_ty, .direct); |
| 2059 | return self.todo("binary operations for composite integers", .{}); | 2187 | |
| 2188 | switch (ptr_ty.ptrSize()) { | ||
| 2189 | .One => { | ||
| 2190 | // Pointer to array | ||
| 2191 | // TODO: Is this correct? | ||
| 2192 | return try self.accessChain(result_ty_ref, ptr_id, &.{offset_id}); | ||
| 2060 | }, | 2193 | }, |
| 2061 | .float => 0, | 2194 | .C, .Many => { |
| 2062 | .bool => 1, | 2195 | return try self.ptrAccessChain(result_ty_ref, ptr_id, offset_id, &.{}); |
| 2063 | .strange_integer => blk: { | ||
| 2064 | const op_ty_ref = try self.resolveType(op_ty, .direct); | ||
| 2065 | lhs_id = try self.maskStrangeInt(op_ty_ref, lhs_id, info.bits); | ||
| 2066 | rhs_id = try self.maskStrangeInt(op_ty_ref, rhs_id, info.bits); | ||
| 2067 | break :blk switch (info.signedness) { | ||
| 2068 | .signed => @as(usize, 1), | ||
| 2069 | .unsigned => @as(usize, 2), | ||
| 2070 | }; | ||
| 2071 | }, | 2196 | }, |
| 2072 | .integer => switch (info.signedness) { | 2197 | .Slice => { |
| 2073 | .signed => @as(usize, 1), | 2198 | // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does. |
| 2074 | .unsigned => @as(usize, 2), | 2199 | const slice_ptr_id = try self.extractField(result_ty, ptr_id, 0); |
| 2200 | return try self.ptrAccessChain(result_ty_ref, slice_ptr_id, offset_id, &.{}); | ||
| 2075 | }, | 2201 | }, |
| 2076 | }; | 2202 | } |
| 2203 | } | ||
| 2077 | 2204 | ||
| 2078 | const operands = .{ | 2205 | fn airPtrAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2079 | .id_result_type = result_type_id, | 2206 | if (self.liveness.isUnused(inst)) return null; |
| 2080 | .id_result = result_id, | 2207 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2081 | .operand_1 = lhs_id, | 2208 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2082 | .operand_2 = rhs_id, | 2209 | const ptr_id = try self.resolve(bin_op.lhs); |
| 2083 | }; | 2210 | const offset_id = try self.resolve(bin_op.rhs); |
| 2211 | const ptr_ty = self.air.typeOf(bin_op.lhs); | ||
| 2212 | const result_ty = self.air.typeOfIndex(inst); | ||
| 2084 | 2213 | ||
| 2085 | switch (opcode_index) { | 2214 | return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id); |
| 2086 | 0 => try self.func.body.emit(self.spv.gpa, fop, operands), | 2215 | } |
| 2087 | 1 => try self.func.body.emit(self.spv.gpa, sop, operands), | 2216 | |
| 2088 | 2 => try self.func.body.emit(self.spv.gpa, uop, operands), | 2217 | fn airPtrSub(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2089 | else => unreachable, | 2218 | if (self.liveness.isUnused(inst)) return null; |
| 2090 | } | 2219 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2220 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 2221 | const ptr_id = try self.resolve(bin_op.lhs); | ||
| 2222 | const ptr_ty = self.air.typeOf(bin_op.lhs); | ||
| 2223 | const offset_id = try self.resolve(bin_op.rhs); | ||
| 2224 | const offset_ty = self.air.typeOf(bin_op.rhs); | ||
| 2225 | const offset_ty_ref = try self.resolveType(offset_ty, .direct); | ||
| 2226 | const result_ty = self.air.typeOfIndex(inst); | ||
| 2227 | |||
| 2228 | const negative_offset_id = self.spv.allocId(); | ||
| 2229 | try self.func.body.emit(self.spv.gpa, .OpSNegate, .{ | ||
| 2230 | .id_result_type = self.typeId(offset_ty_ref), | ||
| 2231 | .id_result = negative_offset_id, | ||
| 2232 | .operand = offset_id, | ||
| 2233 | }); | ||
| 2234 | return try self.ptrAdd(result_ty, ptr_ty, ptr_id, negative_offset_id); | ||
| 2235 | } | ||
| 2236 | |||
| 2237 | fn cmp( | ||
| 2238 | self: *DeclGen, | ||
| 2239 | comptime op: std.math.CompareOperator, | ||
| 2240 | bool_ty_id: IdRef, | ||
| 2241 | ty: Type, | ||
| 2242 | lhs_id: IdRef, | ||
| 2243 | rhs_id: IdRef, | ||
| 2244 | ) !IdRef { | ||
| 2245 | var cmp_lhs_id = lhs_id; | ||
| 2246 | var cmp_rhs_id = rhs_id; | ||
| 2247 | const opcode: Opcode = opcode: { | ||
| 2248 | var int_buffer: Type.Payload.Bits = undefined; | ||
| 2249 | const op_ty = switch (ty.zigTypeTag()) { | ||
| 2250 | .Int, .Bool, .Float => ty, | ||
| 2251 | .Enum => ty.intTagType(&int_buffer), | ||
| 2252 | .ErrorSet => Type.u16, | ||
| 2253 | .Pointer => blk: { | ||
| 2254 | // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are | ||
| 2255 | // currently not implemented in the SPIR-V LLVM translator. Thus, we emit these using | ||
| 2256 | // OpConvertPtrToU... | ||
| 2257 | cmp_lhs_id = self.spv.allocId(); | ||
| 2258 | cmp_rhs_id = self.spv.allocId(); | ||
| 2259 | |||
| 2260 | const usize_ty_id = self.typeId(try self.sizeType()); | ||
| 2261 | |||
| 2262 | try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ | ||
| 2263 | .id_result_type = usize_ty_id, | ||
| 2264 | .id_result = cmp_lhs_id, | ||
| 2265 | .pointer = lhs_id, | ||
| 2266 | }); | ||
| 2267 | |||
| 2268 | try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{ | ||
| 2269 | .id_result_type = usize_ty_id, | ||
| 2270 | .id_result = cmp_rhs_id, | ||
| 2271 | .pointer = rhs_id, | ||
| 2272 | }); | ||
| 2091 | 2273 | ||
| 2274 | break :blk Type.usize; | ||
| 2275 | }, | ||
| 2276 | .Optional => unreachable, // TODO | ||
| 2277 | else => unreachable, | ||
| 2278 | }; | ||
| 2279 | |||
| 2280 | const info = try self.arithmeticTypeInfo(op_ty); | ||
| 2281 | const signedness = switch (info.class) { | ||
| 2282 | .composite_integer => { | ||
| 2283 | return self.todo("binary operations for composite integers", .{}); | ||
| 2284 | }, | ||
| 2285 | .float => break :opcode switch (op) { | ||
| 2286 | .eq => .OpFOrdEqual, | ||
| 2287 | .neq => .OpFOrdNotEqual, | ||
| 2288 | .lt => .OpFOrdLessThan, | ||
| 2289 | .lte => .OpFOrdLessThanEqual, | ||
| 2290 | .gt => .OpFOrdGreaterThan, | ||
| 2291 | .gte => .OpFOrdGreaterThanEqual, | ||
| 2292 | }, | ||
| 2293 | .bool => break :opcode switch (op) { | ||
| 2294 | .eq => .OpIEqual, | ||
| 2295 | .neq => .OpINotEqual, | ||
| 2296 | else => unreachable, | ||
| 2297 | }, | ||
| 2298 | .strange_integer => sign: { | ||
| 2299 | const op_ty_ref = try self.resolveType(op_ty, .direct); | ||
| 2300 | // Mask operands before performing comparison. | ||
| 2301 | cmp_lhs_id = try self.maskStrangeInt(op_ty_ref, cmp_lhs_id, info.bits); | ||
| 2302 | cmp_rhs_id = try self.maskStrangeInt(op_ty_ref, cmp_rhs_id, info.bits); | ||
| 2303 | break :sign info.signedness; | ||
| 2304 | }, | ||
| 2305 | .integer => info.signedness, | ||
| 2306 | }; | ||
| 2307 | |||
| 2308 | break :opcode switch (signedness) { | ||
| 2309 | .unsigned => switch (op) { | ||
| 2310 | .eq => .OpIEqual, | ||
| 2311 | .neq => .OpINotEqual, | ||
| 2312 | .lt => .OpULessThan, | ||
| 2313 | .lte => .OpULessThanEqual, | ||
| 2314 | .gt => .OpUGreaterThan, | ||
| 2315 | .gte => .OpUGreaterThanEqual, | ||
| 2316 | }, | ||
| 2317 | .signed => switch (op) { | ||
| 2318 | .eq => .OpIEqual, | ||
| 2319 | .neq => .OpINotEqual, | ||
| 2320 | .lt => .OpSLessThan, | ||
| 2321 | .lte => .OpSLessThanEqual, | ||
| 2322 | .gt => .OpSGreaterThan, | ||
| 2323 | .gte => .OpSGreaterThanEqual, | ||
| 2324 | }, | ||
| 2325 | }; | ||
| 2326 | }; | ||
| 2327 | |||
| 2328 | const result_id = self.spv.allocId(); | ||
| 2329 | try self.func.body.emitRaw(self.spv.gpa, opcode, 4); | ||
| 2330 | self.func.body.writeOperand(spec.IdResultType, bool_ty_id); | ||
| 2331 | self.func.body.writeOperand(spec.IdResult, result_id); | ||
| 2332 | self.func.body.writeOperand(spec.IdResultType, cmp_lhs_id); | ||
| 2333 | self.func.body.writeOperand(spec.IdResultType, cmp_rhs_id); | ||
| 2092 | return result_id; | 2334 | return result_id; |
| 2093 | } | 2335 | } |
| 2094 | 2336 | ||
| 2095 | fn bitcast(self: *DeclGen, target_type_id: IdResultType, value_id: IdRef) !IdRef { | 2337 | fn airCmp( |
| 2338 | self: *DeclGen, | ||
| 2339 | inst: Air.Inst.Index, | ||
| 2340 | comptime op: std.math.CompareOperator, | ||
| 2341 | ) !?IdRef { | ||
| 2342 | if (self.liveness.isUnused(inst)) return null; | ||
| 2343 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | ||
| 2344 | const lhs_id = try self.resolve(bin_op.lhs); | ||
| 2345 | const rhs_id = try self.resolve(bin_op.rhs); | ||
| 2346 | const bool_ty_id = try self.resolveTypeId(Type.bool); | ||
| 2347 | const ty = self.air.typeOf(bin_op.lhs); | ||
| 2348 | assert(ty.eql(self.air.typeOf(bin_op.rhs), self.module)); | ||
| 2349 | |||
| 2350 | return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id); | ||
| 2351 | } | ||
| 2352 | |||
| 2353 | fn bitCast( | ||
| 2354 | self: *DeclGen, | ||
| 2355 | dst_ty: Type, | ||
| 2356 | src_ty: Type, | ||
| 2357 | src_id: IdRef, | ||
| 2358 | ) !IdRef { | ||
| 2359 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); | ||
| 2096 | const result_id = self.spv.allocId(); | 2360 | const result_id = self.spv.allocId(); |
| 2097 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 2361 | |
| 2098 | .id_result_type = target_type_id, | 2362 | // TODO: Some more cases are missing here |
| 2099 | .id_result = result_id, | 2363 | // See fn bitCast in llvm.zig |
| 2100 | .operand = value_id, | 2364 | |
| 2101 | }); | 2365 | if (src_ty.zigTypeTag() == .Int and dst_ty.isPtrAtRuntime()) { |
| 2366 | try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ | ||
| 2367 | .id_result_type = self.typeId(dst_ty_ref), | ||
| 2368 | .id_result = result_id, | ||
| 2369 | .integer_value = src_id, | ||
| 2370 | }); | ||
| 2371 | } else { | ||
| 2372 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | ||
| 2373 | .id_result_type = self.typeId(dst_ty_ref), | ||
| 2374 | .id_result = result_id, | ||
| 2375 | .operand = src_id, | ||
| 2376 | }); | ||
| 2377 | } | ||
| 2102 | return result_id; | 2378 | return result_id; |
| 2103 | } | 2379 | } |
| 2104 | 2380 | ||
| 2105 | fn airBitcast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2381 | fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2106 | if (self.liveness.isUnused(inst)) return null; | 2382 | if (self.liveness.isUnused(inst)) return null; |
| 2107 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2383 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2108 | const operand_id = try self.resolve(ty_op.operand); | 2384 | const operand_id = try self.resolve(ty_op.operand); |
| 2109 | const result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst)); | 2385 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 2110 | return try self.bitcast(result_type_id, operand_id); | 2386 | const result_ty = self.air.typeOfIndex(inst); |
| 2387 | return try self.bitCast(result_ty, operand_ty, operand_id); | ||
| 2111 | } | 2388 | } |
| 2112 | 2389 | ||
| 2113 | fn airIntcast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2390 | fn airIntCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2114 | if (self.liveness.isUnused(inst)) return null; | 2391 | if (self.liveness.isUnused(inst)) return null; |
| 2115 | 2392 | ||
| 2116 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2393 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2117 | const operand_id = try self.resolve(ty_op.operand); | 2394 | const operand_id = try self.resolve(ty_op.operand); |
| 2118 | const dest_ty = self.air.typeOfIndex(inst); | 2395 | const dest_ty = self.air.typeOfIndex(inst); |
| 2119 | const dest_info = try self.arithmeticTypeInfo(dest_ty); | ||
| 2120 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 2396 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 2121 | 2397 | ||
| 2398 | const target = self.getTarget(); | ||
| 2399 | const dest_info = dest_ty.intInfo(target); | ||
| 2400 | |||
| 2401 | // TODO: Masking? | ||
| 2402 | |||
| 2122 | const result_id = self.spv.allocId(); | 2403 | const result_id = self.spv.allocId(); |
| 2123 | switch (dest_info.signedness) { | 2404 | switch (dest_info.signedness) { |
| 2124 | .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ | 2405 | .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{ |
| ... | @@ -2221,11 +2502,7 @@ pub const DeclGen = struct { | ... | @@ -2221,11 +2502,7 @@ pub const DeclGen = struct { |
| 2221 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2502 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2222 | const field_ty = self.air.typeOfIndex(inst); | 2503 | const field_ty = self.air.typeOfIndex(inst); |
| 2223 | const operand_id = try self.resolve(ty_op.operand); | 2504 | const operand_id = try self.resolve(ty_op.operand); |
| 2224 | return try self.extractField( | 2505 | return try self.extractField(field_ty, operand_id, field); |
| 2225 | field_ty, | ||
| 2226 | operand_id, | ||
| 2227 | field, | ||
| 2228 | ); | ||
| 2229 | } | 2506 | } |
| 2230 | 2507 | ||
| 2231 | fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2508 | fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -2233,30 +2510,14 @@ pub const DeclGen = struct { | ... | @@ -2233,30 +2510,14 @@ pub const DeclGen = struct { |
| 2233 | const slice_ty = self.air.typeOf(bin_op.lhs); | 2510 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 2234 | if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; | 2511 | if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; |
| 2235 | 2512 | ||
| 2236 | const slice = try self.resolve(bin_op.lhs); | 2513 | const slice_id = try self.resolve(bin_op.lhs); |
| 2237 | const index = try self.resolve(bin_op.rhs); | 2514 | const index_id = try self.resolve(bin_op.rhs); |
| 2238 | |||
| 2239 | const spv_ptr_ty = try self.resolveTypeId(self.air.typeOfIndex(inst)); | ||
| 2240 | 2515 | ||
| 2241 | const slice_ptr = blk: { | 2516 | const ptr_ty = self.air.typeOfIndex(inst); |
| 2242 | const result_id = self.spv.allocId(); | 2517 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); |
| 2243 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | ||
| 2244 | .id_result_type = spv_ptr_ty, | ||
| 2245 | .id_result = result_id, | ||
| 2246 | .composite = slice, | ||
| 2247 | .indexes = &.{0}, | ||
| 2248 | }); | ||
| 2249 | break :blk result_id; | ||
| 2250 | }; | ||
| 2251 | 2518 | ||
| 2252 | const result_id = self.spv.allocId(); | 2519 | const slice_ptr = try self.extractField(ptr_ty, slice_id, 0); |
| 2253 | try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ | 2520 | return try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{}); |
| 2254 | .id_result_type = spv_ptr_ty, | ||
| 2255 | .id_result = result_id, | ||
| 2256 | .base = slice_ptr, | ||
| 2257 | .element = index, | ||
| 2258 | }); | ||
| 2259 | return result_id; | ||
| 2260 | } | 2521 | } |
| 2261 | 2522 | ||
| 2262 | fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2523 | fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -2264,61 +2525,64 @@ pub const DeclGen = struct { | ... | @@ -2264,61 +2525,64 @@ pub const DeclGen = struct { |
| 2264 | const slice_ty = self.air.typeOf(bin_op.lhs); | 2525 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 2265 | if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; | 2526 | if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; |
| 2266 | 2527 | ||
| 2267 | const slice = try self.resolve(bin_op.lhs); | 2528 | const slice_id = try self.resolve(bin_op.lhs); |
| 2268 | const index = try self.resolve(bin_op.rhs); | 2529 | const index_id = try self.resolve(bin_op.rhs); |
| 2269 | 2530 | ||
| 2270 | var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 2531 | var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2271 | const ptr_ty_id = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf)); | 2532 | const ptr_ty = slice_ty.slicePtrFieldType(&slice_buf); |
| 2272 | 2533 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); | |
| 2273 | const slice_ptr = blk: { | ||
| 2274 | const result_id = self.spv.allocId(); | ||
| 2275 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | ||
| 2276 | .id_result_type = ptr_ty_id, | ||
| 2277 | .id_result = result_id, | ||
| 2278 | .composite = slice, | ||
| 2279 | .indexes = &.{0}, | ||
| 2280 | }); | ||
| 2281 | break :blk result_id; | ||
| 2282 | }; | ||
| 2283 | |||
| 2284 | const elem_ptr = blk: { | ||
| 2285 | const result_id = self.spv.allocId(); | ||
| 2286 | try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ | ||
| 2287 | .id_result_type = ptr_ty_id, | ||
| 2288 | .id_result = result_id, | ||
| 2289 | .base = slice_ptr, | ||
| 2290 | .element = index, | ||
| 2291 | }); | ||
| 2292 | break :blk result_id; | ||
| 2293 | }; | ||
| 2294 | 2534 | ||
| 2535 | const slice_ptr = try self.extractField(ptr_ty, slice_id, 0); | ||
| 2536 | const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{}); | ||
| 2295 | return try self.load(slice_ty, elem_ptr); | 2537 | return try self.load(slice_ty, elem_ptr); |
| 2296 | } | 2538 | } |
| 2297 | 2539 | ||
| 2540 | fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef { | ||
| 2541 | // Construct new pointer type for the resulting pointer | ||
| 2542 | const elem_ty = ptr_ty.elemType2(); // use elemType() so that we get T for *[N]T. | ||
| 2543 | const elem_ty_ref = try self.resolveType(elem_ty, .direct); | ||
| 2544 | const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace()), 0); | ||
| 2545 | if (ptr_ty.isSinglePointer()) { | ||
| 2546 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | ||
| 2547 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | ||
| 2548 | return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id}); | ||
| 2549 | } else { | ||
| 2550 | // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain | ||
| 2551 | return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{}); | ||
| 2552 | } | ||
| 2553 | } | ||
| 2554 | |||
| 2298 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2555 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2299 | if (self.liveness.isUnused(inst)) return null; | 2556 | if (self.liveness.isUnused(inst)) return null; |
| 2300 | 2557 | ||
| 2301 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2558 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2302 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2559 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2303 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 2560 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2304 | const result_ty = self.air.typeOfIndex(inst); | ||
| 2305 | const elem_ty = ptr_ty.childType(); | 2561 | const elem_ty = ptr_ty.childType(); |
| 2306 | // TODO: Make this return a null ptr or something | 2562 | // TODO: Make this return a null ptr or something |
| 2307 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; | 2563 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; |
| 2308 | 2564 | ||
| 2309 | const result_type_id = try self.resolveTypeId(result_ty); | 2565 | const ptr_id = try self.resolve(bin_op.lhs); |
| 2310 | const base_ptr = try self.resolve(bin_op.lhs); | 2566 | const index_id = try self.resolve(bin_op.rhs); |
| 2311 | const rhs = try self.resolve(bin_op.rhs); | 2567 | return try self.ptrElemPtr(ptr_ty, ptr_id, index_id); |
| 2568 | } | ||
| 2312 | 2569 | ||
| 2313 | const result_id = self.spv.allocId(); | 2570 | fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2314 | const indexes = [_]IdRef{rhs}; | 2571 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2315 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 2572 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 2316 | .id_result_type = result_type_id, | 2573 | const ptr_id = try self.resolve(bin_op.lhs); |
| 2317 | .id_result = result_id, | 2574 | const index_id = try self.resolve(bin_op.rhs); |
| 2318 | .base = base_ptr, | 2575 | |
| 2319 | .indexes = &indexes, | 2576 | const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id); |
| 2320 | }); | 2577 | |
| 2321 | return result_id; | 2578 | // If we have a pointer-to-array, construct an element pointer to use with load() |
| 2579 | // If we pass ptr_ty directly, it will attempt to load the entire array rather than | ||
| 2580 | // just an element. | ||
| 2581 | var elem_ptr_info = ptr_ty.ptrInfo(); | ||
| 2582 | elem_ptr_info.data.size = .One; | ||
| 2583 | const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base); | ||
| 2584 | |||
| 2585 | return try self.load(elem_ptr_ty, elem_ptr_id); | ||
| 2322 | } | 2586 | } |
| 2323 | 2587 | ||
| 2324 | fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2588 | fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -2344,24 +2608,15 @@ pub const DeclGen = struct { | ... | @@ -2344,24 +2608,15 @@ pub const DeclGen = struct { |
| 2344 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; | 2608 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 2345 | 2609 | ||
| 2346 | const struct_ty = self.air.typeOf(struct_field.struct_operand); | 2610 | const struct_ty = self.air.typeOf(struct_field.struct_operand); |
| 2347 | const object = try self.resolve(struct_field.struct_operand); | 2611 | const object_id = try self.resolve(struct_field.struct_operand); |
| 2348 | const field_index = struct_field.field_index; | 2612 | const field_index = struct_field.field_index; |
| 2349 | const field_ty = struct_ty.structFieldType(field_index); | 2613 | const field_ty = struct_ty.structFieldType(field_index); |
| 2350 | const field_ty_id = try self.resolveTypeId(field_ty); | ||
| 2351 | 2614 | ||
| 2352 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) return null; | 2615 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) return null; |
| 2353 | 2616 | ||
| 2354 | assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. | 2617 | assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. |
| 2355 | 2618 | ||
| 2356 | const result_id = self.spv.allocId(); | 2619 | return try self.extractField(field_ty, object_id, field_index); |
| 2357 | const indexes = [_]u32{field_index}; | ||
| 2358 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | ||
| 2359 | .id_result_type = field_ty_id, | ||
| 2360 | .id_result = result_id, | ||
| 2361 | .composite = object, | ||
| 2362 | .indexes = &indexes, | ||
| 2363 | }); | ||
| 2364 | return result_id; | ||
| 2365 | } | 2620 | } |
| 2366 | 2621 | ||
| 2367 | fn structFieldPtr( | 2622 | fn structFieldPtr( |
| ... | @@ -2379,16 +2634,8 @@ pub const DeclGen = struct { | ... | @@ -2379,16 +2634,8 @@ pub const DeclGen = struct { |
| 2379 | const u32_ty_id = self.typeId(try self.intType(.unsigned, 32)); | 2634 | const u32_ty_id = self.typeId(try self.intType(.unsigned, 32)); |
| 2380 | const field_index_id = self.spv.allocId(); | 2635 | const field_index_id = self.spv.allocId(); |
| 2381 | try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index }); | 2636 | try self.spv.emitConstant(u32_ty_id, field_index_id, .{ .uint32 = field_index }); |
| 2382 | const result_id = self.spv.allocId(); | 2637 | const result_ty_ref = try self.resolveType(result_ptr_ty, .direct); |
| 2383 | const result_type_id = try self.resolveTypeId(result_ptr_ty); | 2638 | return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id}); |
| 2384 | const indexes = [_]IdRef{field_index_id}; | ||
| 2385 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | ||
| 2386 | .id_result_type = result_type_id, | ||
| 2387 | .id_result = result_id, | ||
| 2388 | .base = object_ptr, | ||
| 2389 | .indexes = &indexes, | ||
| 2390 | }); | ||
| 2391 | return result_id; | ||
| 2392 | }, | 2639 | }, |
| 2393 | }, | 2640 | }, |
| 2394 | else => unreachable, // TODO | 2641 | else => unreachable, // TODO |
| ... | @@ -2422,76 +2669,45 @@ pub const DeclGen = struct { | ... | @@ -2422,76 +2669,45 @@ pub const DeclGen = struct { |
| 2422 | return result_id; | 2669 | return result_id; |
| 2423 | } | 2670 | } |
| 2424 | 2671 | ||
| 2425 | fn variable( | 2672 | // Allocate a function-local variable, with possible initializer. |
| 2673 | // This function returns a pointer to a variable of type `ty_ref`, | ||
| 2674 | // which is in the Generic address space. The variable is actually | ||
| 2675 | // placed in the Function address space. | ||
| 2676 | fn alloc( | ||
| 2426 | self: *DeclGen, | 2677 | self: *DeclGen, |
| 2427 | comptime context: enum { function, global }, | 2678 | ty_ref: SpvType.Ref, |
| 2428 | result_id: IdRef, | ||
| 2429 | ptr_ty_ref: SpvType.Ref, | ||
| 2430 | initializer: ?IdRef, | 2679 | initializer: ?IdRef, |
| 2431 | ) !void { | 2680 | ) !IdRef { |
| 2432 | const storage_class = self.spv.typeRefType(ptr_ty_ref).payload(.pointer).storage_class; | 2681 | const fn_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Function, 0); |
| 2433 | const actual_storage_class = switch (storage_class) { | 2682 | const general_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Generic, 0); |
| 2434 | .Generic => switch (context) { | ||
| 2435 | .function => .Function, | ||
| 2436 | .global => .CrossWorkgroup, | ||
| 2437 | }, | ||
| 2438 | else => storage_class, | ||
| 2439 | }; | ||
| 2440 | const actual_ptr_ty_ref = switch (storage_class) { | ||
| 2441 | .Generic => try self.spv.changePtrStorageClass(ptr_ty_ref, actual_storage_class), | ||
| 2442 | else => ptr_ty_ref, | ||
| 2443 | }; | ||
| 2444 | const alloc_result_id = switch (storage_class) { | ||
| 2445 | .Generic => self.spv.allocId(), | ||
| 2446 | else => result_id, | ||
| 2447 | }; | ||
| 2448 | 2683 | ||
| 2449 | const section = switch (actual_storage_class) { | 2684 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 2450 | .Generic => unreachable, | 2685 | // directly generate them into func.prologue instead of the body. |
| 2451 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to | 2686 | const var_id = self.spv.allocId(); |
| 2452 | // directly generate them into func.prologue instead of the body. | 2687 | try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ |
| 2453 | .Function => &self.func.prologue, | 2688 | .id_result_type = self.typeId(fn_ptr_ty_ref), |
| 2454 | else => &self.spv.sections.types_globals_constants, | 2689 | .id_result = var_id, |
| 2455 | }; | 2690 | .storage_class = .Function, |
| 2456 | try section.emit(self.spv.gpa, .OpVariable, .{ | ||
| 2457 | .id_result_type = self.typeId(actual_ptr_ty_ref), | ||
| 2458 | .id_result = alloc_result_id, | ||
| 2459 | .storage_class = actual_storage_class, | ||
| 2460 | .initializer = initializer, | 2691 | .initializer = initializer, |
| 2461 | }); | 2692 | }); |
| 2462 | 2693 | ||
| 2463 | if (storage_class != .Generic) { | 2694 | // Convert to a generic pointer |
| 2464 | return; | 2695 | const result_id = self.spv.allocId(); |
| 2465 | } | 2696 | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 2466 | 2697 | .id_result_type = self.typeId(general_ptr_ty_ref), | |
| 2467 | // Now we need to convert the pointer. | 2698 | .id_result = result_id, |
| 2468 | // If this is a function local, we need to perform the conversion at runtime. Otherwise, we can do | 2699 | .pointer = var_id, |
| 2469 | // it ahead of time using OpSpecConstantOp. | 2700 | }); |
| 2470 | switch (actual_storage_class) { | 2701 | return result_id; |
| 2471 | .Function => try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ | ||
| 2472 | .id_result_type = self.typeId(ptr_ty_ref), | ||
| 2473 | .id_result = result_id, | ||
| 2474 | .pointer = alloc_result_id, | ||
| 2475 | }), | ||
| 2476 | // TODO: Can we do without this cast or move it to runtime? | ||
| 2477 | else => { | ||
| 2478 | const const_ptr_id = try self.makePointerConstant(section, actual_ptr_ty_ref, alloc_result_id); | ||
| 2479 | try section.emitSpecConstantOp(self.spv.gpa, .OpPtrCastToGeneric, .{ | ||
| 2480 | .id_result_type = self.typeId(ptr_ty_ref), | ||
| 2481 | .id_result = result_id, | ||
| 2482 | .pointer = const_ptr_id, | ||
| 2483 | }); | ||
| 2484 | }, | ||
| 2485 | } | ||
| 2486 | } | 2702 | } |
| 2487 | 2703 | ||
| 2488 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2704 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2489 | if (self.liveness.isUnused(inst)) return null; | 2705 | if (self.liveness.isUnused(inst)) return null; |
| 2490 | const ty = self.air.typeOfIndex(inst); | 2706 | const ptr_ty = self.air.typeOfIndex(inst); |
| 2491 | const result_ty_ref = try self.resolveType(ty, .direct); | 2707 | assert(ptr_ty.ptrAddressSpace() == .generic); |
| 2492 | const result_id = self.spv.allocId(); | 2708 | const child_ty = ptr_ty.childType(); |
| 2493 | try self.variable(.function, result_id, result_ty_ref, null); | 2709 | const child_ty_ref = try self.resolveType(child_ty, .indirect); |
| 2494 | return result_id; | 2710 | return try self.alloc(child_ty_ref, null); |
| 2495 | } | 2711 | } |
| 2496 | 2712 | ||
| 2497 | fn airArg(self: *DeclGen) IdRef { | 2713 | fn airArg(self: *DeclGen) IdRef { |
| ... | @@ -2778,13 +2994,7 @@ pub const DeclGen = struct { | ... | @@ -2778,13 +2994,7 @@ pub const DeclGen = struct { |
| 2778 | } | 2994 | } |
| 2779 | 2995 | ||
| 2780 | const err_union_ty_ref = try self.resolveType(err_union_ty, .direct); | 2996 | const err_union_ty_ref = try self.resolveType(err_union_ty, .direct); |
| 2781 | const result_id = self.spv.allocId(); | 2997 | return try self.constructStruct(err_union_ty_ref, members.slice()); |
| 2782 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | ||
| 2783 | .id_result_type = self.typeId(err_union_ty_ref), | ||
| 2784 | .id_result = result_id, | ||
| 2785 | .constituents = members.slice(), | ||
| 2786 | }); | ||
| 2787 | return result_id; | ||
| 2788 | } | 2998 | } |
| 2789 | 2999 | ||
| 2790 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { | 3000 | fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef { |
| ... | @@ -2884,14 +3094,8 @@ pub const DeclGen = struct { | ... | @@ -2884,14 +3094,8 @@ pub const DeclGen = struct { |
| 2884 | } | 3094 | } |
| 2885 | 3095 | ||
| 2886 | const optional_ty_ref = try self.resolveType(optional_ty, .direct); | 3096 | const optional_ty_ref = try self.resolveType(optional_ty, .direct); |
| 2887 | const result_id = self.spv.allocId(); | ||
| 2888 | const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; | 3097 | const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; |
| 2889 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | 3098 | return try self.constructStruct(optional_ty_ref, &members); |
| 2890 | .id_result_type = self.typeId(optional_ty_ref), | ||
| 2891 | .id_result = result_id, | ||
| 2892 | .constituents = &members, | ||
| 2893 | }); | ||
| 2894 | return result_id; | ||
| 2895 | } | 3099 | } |
| 2896 | 3100 | ||
| 2897 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { | 3101 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { |
src/codegen/spirv/Module.zig+10| ... | @@ -774,6 +774,16 @@ pub fn changePtrStorageClass(self: *Module, ptr_ty_ref: Type.Ref, new_storage_cl | ... | @@ -774,6 +774,16 @@ pub fn changePtrStorageClass(self: *Module, ptr_ty_ref: Type.Ref, new_storage_cl |
| 774 | return try self.resolveType(Type.initPayload(&payload.base)); | 774 | return try self.resolveType(Type.initPayload(&payload.base)); |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | pub fn constComposite(self: *Module, ty_ref: Type.Ref, members: []const IdRef) !IdRef { | ||
| 778 | const result_id = self.allocId(); | ||
| 779 | try self.sections.types_globals_constants.emit(self.gpa, .OpSpecConstantComposite, .{ | ||
| 780 | .id_result_type = self.typeId(ty_ref), | ||
| 781 | .id_result = result_id, | ||
| 782 | .constituents = members, | ||
| 783 | }); | ||
| 784 | return result_id; | ||
| 785 | } | ||
| 786 | |||
| 777 | pub fn emitConstant( | 787 | pub fn emitConstant( |
| 778 | self: *Module, | 788 | self: *Module, |
| 779 | ty_id: IdRef, | 789 | ty_id: IdRef, |
test/behavior/align.zig-6| ... | @@ -33,8 +33,6 @@ test "default alignment allows unspecified in type syntax" { | ... | @@ -33,8 +33,6 @@ test "default alignment allows unspecified in type syntax" { |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | test "implicitly decreasing pointer alignment" { | 35 | test "implicitly decreasing pointer alignment" { |
| 36 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 37 | |||
| 38 | const a: u32 align(4) = 3; | 36 | const a: u32 align(4) = 3; |
| 39 | const b: u32 align(8) = 4; | 37 | const b: u32 align(8) = 4; |
| 40 | try expect(addUnaligned(&a, &b) == 7); | 38 | try expect(addUnaligned(&a, &b) == 7); |
| ... | @@ -45,8 +43,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | ... | @@ -45,8 +43,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { |
| 45 | } | 43 | } |
| 46 | 44 | ||
| 47 | test "@alignCast pointers" { | 45 | test "@alignCast pointers" { |
| 48 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 49 | |||
| 50 | var x: u32 align(4) = 1; | 46 | var x: u32 align(4) = 1; |
| 51 | expectsOnly1(&x); | 47 | expectsOnly1(&x); |
| 52 | try expect(x == 2); | 48 | try expect(x == 2); |
| ... | @@ -219,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" { | ... | @@ -219,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" { |
| 219 | } | 215 | } |
| 220 | 216 | ||
| 221 | test "@ptrCast preserves alignment of bigger source" { | 217 | test "@ptrCast preserves alignment of bigger source" { |
| 222 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 223 | |||
| 224 | var x: u32 align(16) = 1234; | 218 | var x: u32 align(16) = 1234; |
| 225 | const ptr = @ptrCast(*u8, &x); | 219 | const ptr = @ptrCast(*u8, &x); |
| 226 | try expect(@TypeOf(ptr) == *align(16) u8); | 220 | try expect(@TypeOf(ptr) == *align(16) u8); |
test/behavior/array.zig-2| ... | @@ -347,7 +347,6 @@ test "read/write through global variable array of struct fields initialized via | ... | @@ -347,7 +347,6 @@ test "read/write through global variable array of struct fields initialized via |
| 347 | test "implicit cast single-item pointer" { | 347 | test "implicit cast single-item pointer" { |
| 348 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 348 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 349 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 349 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 350 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 351 | 350 | ||
| 352 | try testImplicitCastSingleItemPtr(); | 351 | try testImplicitCastSingleItemPtr(); |
| 353 | comptime try testImplicitCastSingleItemPtr(); | 352 | comptime try testImplicitCastSingleItemPtr(); |
| ... | @@ -542,7 +541,6 @@ test "sentinel element count towards the ABI size calculation" { | ... | @@ -542,7 +541,6 @@ test "sentinel element count towards the ABI size calculation" { |
| 542 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 541 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 543 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 542 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 544 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 543 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 545 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 546 | 544 | ||
| 547 | const S = struct { | 545 | const S = struct { |
| 548 | fn doTheTest() !void { | 546 | fn doTheTest() !void { |
test/behavior/asm.zig+4-1| ... | @@ -15,6 +15,10 @@ comptime { | ... | @@ -15,6 +15,10 @@ comptime { |
| 15 | \\.type this_is_my_alias, @function; | 15 | \\.type this_is_my_alias, @function; |
| 16 | \\.set this_is_my_alias, derp; | 16 | \\.set this_is_my_alias, derp; |
| 17 | ); | 17 | ); |
| 18 | } else if (builtin.zig_backend == .stage2_spirv64) { | ||
| 19 | asm ( | ||
| 20 | \\%a = OpString "hello there" | ||
| 21 | ); | ||
| 18 | } | 22 | } |
| 19 | } | 23 | } |
| 20 | 24 | ||
| ... | @@ -24,7 +28,6 @@ test "module level assembly" { | ... | @@ -24,7 +28,6 @@ test "module level assembly" { |
| 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 28 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 25 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 29 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 26 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 30 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 27 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 28 | 31 | ||
| 29 | if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly | 32 | if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly |
| 30 | 33 |
test/behavior/atomics.zig-2| ... | @@ -120,7 +120,6 @@ test "128-bit cmpxchg" { | ... | @@ -120,7 +120,6 @@ test "128-bit cmpxchg" { |
| 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 121 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 121 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 122 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 122 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 123 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 124 | 123 | ||
| 125 | try test_u128_cmpxchg(); | 124 | try test_u128_cmpxchg(); |
| 126 | comptime try test_u128_cmpxchg(); | 125 | comptime try test_u128_cmpxchg(); |
| ... | @@ -313,7 +312,6 @@ test "atomicrmw with 128-bit ints" { | ... | @@ -313,7 +312,6 @@ test "atomicrmw with 128-bit ints" { |
| 313 | 312 | ||
| 314 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 313 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 315 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 314 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 316 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 317 | 315 | ||
| 318 | // TODO "ld.lld: undefined symbol: __sync_lock_test_and_set_16" on -mcpu x86_64 | 316 | // TODO "ld.lld: undefined symbol: __sync_lock_test_and_set_16" on -mcpu x86_64 |
| 319 | if (builtin.cpu.arch == .x86_64 and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | 317 | if (builtin.cpu.arch == .x86_64 and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
test/behavior/basic.zig+1-26| ... | @@ -82,8 +82,6 @@ test "type equality" { | ... | @@ -82,8 +82,6 @@ test "type equality" { |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | test "pointer dereferencing" { | 84 | test "pointer dereferencing" { |
| 85 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 86 | |||
| 87 | var x = @as(i32, 3); | 85 | var x = @as(i32, 3); |
| 88 | const y = &x; | 86 | const y = &x; |
| 89 | 87 | ||
| ... | @@ -134,21 +132,18 @@ fn first4KeysOfHomeRow() []const u8 { | ... | @@ -134,21 +132,18 @@ fn first4KeysOfHomeRow() []const u8 { |
| 134 | 132 | ||
| 135 | test "return string from function" { | 133 | test "return string from function" { |
| 136 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 134 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 137 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 138 | 135 | ||
| 139 | try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); | 136 | try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); |
| 140 | } | 137 | } |
| 141 | 138 | ||
| 142 | test "hex escape" { | 139 | test "hex escape" { |
| 143 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 140 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 144 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 145 | 141 | ||
| 146 | try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); | 142 | try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); |
| 147 | } | 143 | } |
| 148 | 144 | ||
| 149 | test "multiline string" { | 145 | test "multiline string" { |
| 150 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 146 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 151 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 152 | 147 | ||
| 153 | const s1 = | 148 | const s1 = |
| 154 | \\one | 149 | \\one |
| ... | @@ -161,7 +156,6 @@ test "multiline string" { | ... | @@ -161,7 +156,6 @@ test "multiline string" { |
| 161 | 156 | ||
| 162 | test "multiline string comments at start" { | 157 | test "multiline string comments at start" { |
| 163 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 158 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 164 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 165 | 159 | ||
| 166 | const s1 = | 160 | const s1 = |
| 167 | //\\one | 161 | //\\one |
| ... | @@ -174,7 +168,6 @@ test "multiline string comments at start" { | ... | @@ -174,7 +168,6 @@ test "multiline string comments at start" { |
| 174 | 168 | ||
| 175 | test "multiline string comments at end" { | 169 | test "multiline string comments at end" { |
| 176 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 170 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 177 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 178 | 171 | ||
| 179 | const s1 = | 172 | const s1 = |
| 180 | \\one | 173 | \\one |
| ... | @@ -187,7 +180,6 @@ test "multiline string comments at end" { | ... | @@ -187,7 +180,6 @@ test "multiline string comments at end" { |
| 187 | 180 | ||
| 188 | test "multiline string comments in middle" { | 181 | test "multiline string comments in middle" { |
| 189 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 182 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 190 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 191 | 183 | ||
| 192 | const s1 = | 184 | const s1 = |
| 193 | \\one | 185 | \\one |
| ... | @@ -200,7 +192,6 @@ test "multiline string comments in middle" { | ... | @@ -200,7 +192,6 @@ test "multiline string comments in middle" { |
| 200 | 192 | ||
| 201 | test "multiline string comments at multiple places" { | 193 | test "multiline string comments at multiple places" { |
| 202 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 194 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 203 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 204 | 195 | ||
| 205 | const s1 = | 196 | const s1 = |
| 206 | \\one | 197 | \\one |
| ... | @@ -214,14 +205,11 @@ test "multiline string comments at multiple places" { | ... | @@ -214,14 +205,11 @@ test "multiline string comments at multiple places" { |
| 214 | } | 205 | } |
| 215 | 206 | ||
| 216 | test "string concatenation simple" { | 207 | test "string concatenation simple" { |
| 217 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 218 | |||
| 219 | try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | 208 | try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); |
| 220 | } | 209 | } |
| 221 | 210 | ||
| 222 | test "array mult operator" { | 211 | test "array mult operator" { |
| 223 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 212 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 224 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 225 | 213 | ||
| 226 | try expect(mem.eql(u8, "ab" ** 5, "ababababab")); | 214 | try expect(mem.eql(u8, "ab" ** 5, "ababababab")); |
| 227 | } | 215 | } |
| ... | @@ -303,8 +291,6 @@ test "function closes over local const" { | ... | @@ -303,8 +291,6 @@ test "function closes over local const" { |
| 303 | } | 291 | } |
| 304 | 292 | ||
| 305 | test "volatile load and store" { | 293 | test "volatile load and store" { |
| 306 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 307 | |||
| 308 | var number: i32 = 1234; | 294 | var number: i32 = 1234; |
| 309 | const ptr = @as(*volatile i32, &number); | 295 | const ptr = @as(*volatile i32, &number); |
| 310 | ptr.* += 1; | 296 | ptr.* += 1; |
| ... | @@ -387,7 +373,6 @@ test "take address of parameter" { | ... | @@ -387,7 +373,6 @@ test "take address of parameter" { |
| 387 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 373 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 388 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 374 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 389 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 375 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 390 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 391 | 376 | ||
| 392 | try testTakeAddressOfParameter(12.34); | 377 | try testTakeAddressOfParameter(12.34); |
| 393 | } | 378 | } |
| ... | @@ -477,7 +462,6 @@ fn nine() u8 { | ... | @@ -477,7 +462,6 @@ fn nine() u8 { |
| 477 | test "struct inside function" { | 462 | test "struct inside function" { |
| 478 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 463 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 479 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 464 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 480 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 481 | 465 | ||
| 482 | try testStructInFn(); | 466 | try testStructInFn(); |
| 483 | comptime try testStructInFn(); | 467 | comptime try testStructInFn(); |
| ... | @@ -599,7 +583,7 @@ test "comptime cast fn to ptr" { | ... | @@ -599,7 +583,7 @@ test "comptime cast fn to ptr" { |
| 599 | } | 583 | } |
| 600 | 584 | ||
| 601 | test "equality compare fn ptrs" { | 585 | test "equality compare fn ptrs" { |
| 602 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 586 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // Test passes but should not |
| 603 | 587 | ||
| 604 | var a = &emptyFn; | 588 | var a = &emptyFn; |
| 605 | try expect(a == a); | 589 | try expect(a == a); |
| ... | @@ -690,8 +674,6 @@ test "explicit cast optional pointers" { | ... | @@ -690,8 +674,6 @@ test "explicit cast optional pointers" { |
| 690 | } | 674 | } |
| 691 | 675 | ||
| 692 | test "pointer comparison" { | 676 | test "pointer comparison" { |
| 693 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 694 | |||
| 695 | const a = @as([]const u8, "a"); | 677 | const a = @as([]const u8, "a"); |
| 696 | const b = &a; | 678 | const b = &a; |
| 697 | try expect(ptrEql(b, b)); | 679 | try expect(ptrEql(b, b)); |
| ... | @@ -704,7 +686,6 @@ test "string concatenation" { | ... | @@ -704,7 +686,6 @@ test "string concatenation" { |
| 704 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 686 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 705 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 687 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 706 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 688 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 707 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 708 | 689 | ||
| 709 | const a = "OK" ++ " IT " ++ "WORKED"; | 690 | const a = "OK" ++ " IT " ++ "WORKED"; |
| 710 | const b = "OK IT WORKED"; | 691 | const b = "OK IT WORKED"; |
| ... | @@ -770,7 +751,6 @@ fn maybe(x: bool) anyerror!?u32 { | ... | @@ -770,7 +751,6 @@ fn maybe(x: bool) anyerror!?u32 { |
| 770 | test "auto created variables have correct alignment" { | 751 | test "auto created variables have correct alignment" { |
| 771 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 752 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 772 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 753 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 773 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 774 | 754 | ||
| 775 | const S = struct { | 755 | const S = struct { |
| 776 | fn foo(str: [*]const u8) u32 { | 756 | fn foo(str: [*]const u8) u32 { |
| ... | @@ -892,8 +872,6 @@ test "catch in block has correct result location" { | ... | @@ -892,8 +872,6 @@ test "catch in block has correct result location" { |
| 892 | } | 872 | } |
| 893 | 873 | ||
| 894 | test "labeled block with runtime branch forwards its result location type to break statements" { | 874 | test "labeled block with runtime branch forwards its result location type to break statements" { |
| 895 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 896 | |||
| 897 | const E = enum { a, b }; | 875 | const E = enum { a, b }; |
| 898 | var a = false; | 876 | var a = false; |
| 899 | const e: E = blk: { | 877 | const e: E = blk: { |
| ... | @@ -1062,8 +1040,6 @@ test "switch inside @as gets correct type" { | ... | @@ -1062,8 +1040,6 @@ test "switch inside @as gets correct type" { |
| 1062 | } | 1040 | } |
| 1063 | 1041 | ||
| 1064 | test "inline call of function with a switch inside the return statement" { | 1042 | test "inline call of function with a switch inside the return statement" { |
| 1065 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1066 | |||
| 1067 | const S = struct { | 1043 | const S = struct { |
| 1068 | inline fn foo(x: anytype) @TypeOf(x) { | 1044 | inline fn foo(x: anytype) @TypeOf(x) { |
| 1069 | return switch (x) { | 1045 | return switch (x) { |
| ... | @@ -1147,7 +1123,6 @@ test "returning an opaque type from a function" { | ... | @@ -1147,7 +1123,6 @@ test "returning an opaque type from a function" { |
| 1147 | test "orelse coercion as function argument" { | 1123 | test "orelse coercion as function argument" { |
| 1148 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1124 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1149 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1125 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1150 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1151 | 1126 | ||
| 1152 | const Loc = struct { start: i32 = -1 }; | 1127 | const Loc = struct { start: i32 = -1 }; |
| 1153 | const Container = struct { | 1128 | const Container = struct { |
test/behavior/bitcast.zig-1| ... | @@ -9,7 +9,6 @@ const native_endian = builtin.target.cpu.arch.endian(); | ... | @@ -9,7 +9,6 @@ const native_endian = builtin.target.cpu.arch.endian(); |
| 9 | 9 | ||
| 10 | test "@bitCast iX -> uX (32, 64)" { | 10 | test "@bitCast iX -> uX (32, 64)" { |
| 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 12 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 13 | 12 | ||
| 14 | const bit_values = [_]usize{ 32, 64 }; | 13 | const bit_values = [_]usize{ 32, 64 }; |
| 15 | 14 |
test/behavior/bitreverse.zig-1| ... | @@ -5,7 +5,6 @@ const minInt = std.math.minInt; | ... | @@ -5,7 +5,6 @@ const minInt = std.math.minInt; |
| 5 | 5 | ||
| 6 | test "@bitReverse large exotic integer" { | 6 | test "@bitReverse large exotic integer" { |
| 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; | ||
| 9 | 8 | ||
| 10 | try expect(@bitReverse(@as(u95, 0x123456789abcdef111213141)) == 0x4146424447bd9eac8f351624); | 9 | try expect(@bitReverse(@as(u95, 0x123456789abcdef111213141)) == 0x4146424447bd9eac8f351624); |
| 11 | } | 10 | } |
test/behavior/call.zig-5| ... | @@ -109,7 +109,6 @@ test "result location of function call argument through runtime condition and st | ... | @@ -109,7 +109,6 @@ test "result location of function call argument through runtime condition and st |
| 109 | 109 | ||
| 110 | test "function call with 40 arguments" { | 110 | test "function call with 40 arguments" { |
| 111 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 111 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 112 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 113 | 112 | ||
| 114 | const S = struct { | 113 | const S = struct { |
| 115 | fn doTheTest(thirty_nine: i32) !void { | 114 | fn doTheTest(thirty_nine: i32) !void { |
| ... | @@ -374,8 +373,6 @@ test "Enum constructed by @Type passed as generic argument" { | ... | @@ -374,8 +373,6 @@ test "Enum constructed by @Type passed as generic argument" { |
| 374 | } | 373 | } |
| 375 | 374 | ||
| 376 | test "generic function with generic function parameter" { | 375 | test "generic function with generic function parameter" { |
| 377 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 378 | |||
| 379 | const S = struct { | 376 | const S = struct { |
| 380 | fn f(comptime a: fn (anytype) anyerror!void, b: anytype) anyerror!void { | 377 | fn f(comptime a: fn (anytype) anyerror!void, b: anytype) anyerror!void { |
| 381 | try a(b); | 378 | try a(b); |
| ... | @@ -388,8 +385,6 @@ test "generic function with generic function parameter" { | ... | @@ -388,8 +385,6 @@ test "generic function with generic function parameter" { |
| 388 | } | 385 | } |
| 389 | 386 | ||
| 390 | test "recursive inline call with comptime known argument" { | 387 | test "recursive inline call with comptime known argument" { |
| 391 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 392 | |||
| 393 | const S = struct { | 388 | const S = struct { |
| 394 | inline fn foo(x: i32) i32 { | 389 | inline fn foo(x: i32) i32 { |
| 395 | if (x <= 0) { | 390 | if (x <= 0) { |
test/behavior/cast.zig-3| ... | @@ -322,7 +322,6 @@ test "peer result null and comptime_int" { | ... | @@ -322,7 +322,6 @@ test "peer result null and comptime_int" { |
| 322 | test "*const ?[*]const T to [*c]const [*c]const T" { | 322 | test "*const ?[*]const T to [*c]const [*c]const T" { |
| 323 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 323 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 324 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 324 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 325 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 326 | 325 | ||
| 327 | var array = [_]u8{ 'o', 'k' }; | 326 | var array = [_]u8{ 'o', 'k' }; |
| 328 | const opt_array_ptr: ?[*]const u8 = &array; | 327 | const opt_array_ptr: ?[*]const u8 = &array; |
| ... | @@ -366,7 +365,6 @@ test "return u8 coercing into ?u32 return type" { | ... | @@ -366,7 +365,6 @@ test "return u8 coercing into ?u32 return type" { |
| 366 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 365 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 367 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 366 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 368 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 367 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 369 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 370 | 368 | ||
| 371 | const S = struct { | 369 | const S = struct { |
| 372 | fn doTheTest() !void { | 370 | fn doTheTest() !void { |
| ... | @@ -428,7 +426,6 @@ test "peer resolve array and const slice" { | ... | @@ -428,7 +426,6 @@ test "peer resolve array and const slice" { |
| 428 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 426 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 429 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 427 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 430 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 428 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 431 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 432 | 429 | ||
| 433 | try testPeerResolveArrayConstSlice(true); | 430 | try testPeerResolveArrayConstSlice(true); |
| 434 | comptime try testPeerResolveArrayConstSlice(true); | 431 | comptime try testPeerResolveArrayConstSlice(true); |
test/behavior/decltest.zig-2| ... | @@ -5,7 +5,5 @@ pub fn the_add_function(a: u32, b: u32) u32 { | ... | @@ -5,7 +5,5 @@ pub fn the_add_function(a: u32, b: u32) u32 { |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | test the_add_function { | 7 | test the_add_function { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 10 | if (the_add_function(1, 2) != 3) unreachable; | 8 | if (the_add_function(1, 2) != 3) unreachable; |
| 11 | } | 9 | } |
test/behavior/defer.zig-3| ... | @@ -23,8 +23,6 @@ fn testBreakContInDefer(x: usize) void { | ... | @@ -23,8 +23,6 @@ fn testBreakContInDefer(x: usize) void { |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | test "defer and labeled break" { | 25 | test "defer and labeled break" { |
| 26 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 27 | |||
| 28 | var i = @as(usize, 0); | 26 | var i = @as(usize, 0); |
| 29 | 27 | ||
| 30 | blk: { | 28 | blk: { |
| ... | @@ -58,7 +56,6 @@ test "return variable while defer expression in scope to modify it" { | ... | @@ -58,7 +56,6 @@ test "return variable while defer expression in scope to modify it" { |
| 58 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 56 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 59 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 57 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 60 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 58 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 61 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 62 | 59 | ||
| 63 | const S = struct { | 60 | const S = struct { |
| 64 | fn doTheTest() !void { | 61 | fn doTheTest() !void { |
test/behavior/duplicated_test_names.zig-2| ... | @@ -15,7 +15,5 @@ comptime { | ... | @@ -15,7 +15,5 @@ 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 | |||
| 20 | if (thingy(1, 2) != 3) unreachable; | 18 | if (thingy(1, 2) != 3) unreachable; |
| 21 | } | 19 | } |
test/behavior/enum.zig-1| ... | @@ -1045,7 +1045,6 @@ test "tag name with assigned enum values" { | ... | @@ -1045,7 +1045,6 @@ test "tag name with assigned enum values" { |
| 1045 | test "@tagName on enum literals" { | 1045 | test "@tagName on enum literals" { |
| 1046 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1046 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1047 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1047 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1048 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1049 | 1048 | ||
| 1050 | try expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); | 1049 | try expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); |
| 1051 | comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); | 1050 | comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); |
test/behavior/error.zig-2| ... | @@ -16,14 +16,12 @@ fn expectError(expected_err: anyerror, observed_err_union: anytype) !void { | ... | @@ -16,14 +16,12 @@ fn expectError(expected_err: anyerror, observed_err_union: anytype) !void { |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | test "error values" { | 18 | test "error values" { |
| 19 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 20 | const a = @errorToInt(error.err1); | 19 | const a = @errorToInt(error.err1); |
| 21 | const b = @errorToInt(error.err2); | 20 | const b = @errorToInt(error.err2); |
| 22 | try expect(a != b); | 21 | try expect(a != b); |
| 23 | } | 22 | } |
| 24 | 23 | ||
| 25 | test "redefinition of error values allowed" { | 24 | test "redefinition of error values allowed" { |
| 26 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 27 | shouldBeNotEqual(error.AnError, error.SecondError); | 25 | shouldBeNotEqual(error.AnError, error.SecondError); |
| 28 | } | 26 | } |
| 29 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { | 27 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { |
test/behavior/eval.zig-3| ... | @@ -23,7 +23,6 @@ test "static add one" { | ... | @@ -23,7 +23,6 @@ test "static add one" { |
| 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 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; | ||
| 27 | 26 | ||
| 28 | try expect(should_be_1235 == 1235); | 27 | try expect(should_be_1235 == 1235); |
| 29 | } | 28 | } |
| ... | @@ -48,8 +47,6 @@ test "inline variable gets result of const if" { | ... | @@ -48,8 +47,6 @@ test "inline variable gets result of const if" { |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | test "static function evaluation" { | 49 | test "static function evaluation" { |
| 51 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 52 | |||
| 53 | try expect(statically_added_number == 3); | 50 | try expect(statically_added_number == 3); |
| 54 | } | 51 | } |
| 55 | const statically_added_number = staticAdd(1, 2); | 52 | const statically_added_number = staticAdd(1, 2); |
test/behavior/floatop.zig-2| ... | @@ -506,7 +506,6 @@ test "@fabs" { | ... | @@ -506,7 +506,6 @@ test "@fabs" { |
| 506 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 506 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 507 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 507 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 508 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 508 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 509 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 510 | 509 | ||
| 511 | comptime try testFabs(); | 510 | comptime try testFabs(); |
| 512 | try testFabs(); | 511 | try testFabs(); |
| ... | @@ -621,7 +620,6 @@ test "@floor" { | ... | @@ -621,7 +620,6 @@ test "@floor" { |
| 621 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 620 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 622 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 621 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 623 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 622 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 624 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 625 | 623 | ||
| 626 | comptime try testFloor(); | 624 | comptime try testFloor(); |
| 627 | try testFloor(); | 625 | try testFloor(); |
test/behavior/fn.zig-4| ... | @@ -5,8 +5,6 @@ const expect = testing.expect; | ... | @@ -5,8 +5,6 @@ const expect = testing.expect; |
| 5 | const expectEqual = testing.expectEqual; | 5 | const expectEqual = testing.expectEqual; |
| 6 | 6 | ||
| 7 | test "params" { | 7 | test "params" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 10 | try expect(testParamsAdd(22, 11) == 33); | 8 | try expect(testParamsAdd(22, 11) == 33); |
| 11 | } | 9 | } |
| 12 | fn testParamsAdd(a: i32, b: i32) i32 { | 10 | fn testParamsAdd(a: i32, b: i32) i32 { |
| ... | @@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { | ... | @@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { |
| 14 | } | 12 | } |
| 15 | 13 | ||
| 16 | test "local variables" { | 14 | test "local variables" { |
| 17 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 18 | |||
| 19 | testLocVars(2); | 15 | testLocVars(2); |
| 20 | } | 16 | } |
| 21 | fn testLocVars(b: i32) void { | 17 | fn testLocVars(b: i32) void { |
test/behavior/fn_delegation.zig-1| ... | @@ -34,7 +34,6 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 { | ... | @@ -34,7 +34,6 @@ fn custom(comptime T: type, comptime num: u64) fn (T) u64 { |
| 34 | test "fn delegation" { | 34 | test "fn delegation" { |
| 35 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 35 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 36 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 36 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 37 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 38 | 37 | ||
| 39 | const foo = Foo{}; | 38 | const foo = Foo{}; |
| 40 | try expect(foo.one() == 11); | 39 | try expect(foo.one() == 11); |
test/behavior/fn_in_struct_in_comptime.zig-2| ... | @@ -13,8 +13,6 @@ fn get_foo() fn (*u8) usize { | ... | @@ -13,8 +13,6 @@ fn get_foo() fn (*u8) usize { |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | test "define a function in an anonymous struct in comptime" { | 15 | test "define a function in an anonymous struct in comptime" { |
| 16 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 17 | |||
| 18 | const foo = get_foo(); | 16 | const foo = get_foo(); |
| 19 | try expect(foo(@intToPtr(*u8, 12345)) == 12345); | 17 | try expect(foo(@intToPtr(*u8, 12345)) == 12345); |
| 20 | } | 18 | } |
test/behavior/for.zig-4| ... | @@ -22,8 +22,6 @@ test "continue in for loop" { | ... | @@ -22,8 +22,6 @@ test "continue in for loop" { |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | test "break from outer for loop" { | 24 | test "break from outer for loop" { |
| 25 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 26 | |||
| 27 | try testBreakOuter(); | 25 | try testBreakOuter(); |
| 28 | comptime try testBreakOuter(); | 26 | comptime try testBreakOuter(); |
| 29 | } | 27 | } |
| ... | @@ -41,8 +39,6 @@ fn testBreakOuter() !void { | ... | @@ -41,8 +39,6 @@ fn testBreakOuter() !void { |
| 41 | } | 39 | } |
| 42 | 40 | ||
| 43 | test "continue outer for loop" { | 41 | test "continue outer for loop" { |
| 44 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 45 | |||
| 46 | try testContinueOuter(); | 42 | try testContinueOuter(); |
| 47 | comptime try testContinueOuter(); | 43 | comptime try testContinueOuter(); |
| 48 | } | 44 | } |
test/behavior/generics.zig-3| ... | @@ -5,8 +5,6 @@ const expect = testing.expect; | ... | @@ -5,8 +5,6 @@ const expect = testing.expect; |
| 5 | const expectEqual = testing.expectEqual; | 5 | const expectEqual = testing.expectEqual; |
| 6 | 6 | ||
| 7 | test "one param, explicit comptime" { | 7 | test "one param, explicit comptime" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | |||
| 10 | var x: usize = 0; | 8 | var x: usize = 0; |
| 11 | x += checkSize(i32); | 9 | x += checkSize(i32); |
| 12 | x += checkSize(bool); | 10 | x += checkSize(bool); |
| ... | @@ -21,7 +19,6 @@ fn checkSize(comptime T: type) usize { | ... | @@ -21,7 +19,6 @@ fn checkSize(comptime T: type) usize { |
| 21 | test "simple generic fn" { | 19 | test "simple generic fn" { |
| 22 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 23 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 21 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 25 | 22 | ||
| 26 | try expect(max(i32, 3, -1) == 3); | 23 | try expect(max(i32, 3, -1) == 3); |
| 27 | try expect(max(u8, 1, 100) == 100); | 24 | try expect(max(u8, 1, 100) == 100); |
test/behavior/if.zig-2| ... | @@ -71,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" { | ... | @@ -71,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" { |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | test "const result loc, runtime if cond, else unreachable" { | 73 | test "const result loc, runtime if cond, else unreachable" { |
| 74 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 75 | |||
| 76 | const Num = enum { One, Two }; | 74 | const Num = enum { One, Two }; |
| 77 | 75 | ||
| 78 | var t = true; | 76 | var t = true; |
test/behavior/inttoptr.zig-1| ... | @@ -14,7 +14,6 @@ test "mutate through ptr initialized with constant intToPtr value" { | ... | @@ -14,7 +14,6 @@ test "mutate through ptr initialized with constant intToPtr value" { |
| 14 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 14 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 15 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 15 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 16 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 16 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 17 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 18 | 17 | ||
| 19 | forceCompilerAnalyzeBranchHardCodedPtrDereference(false); | 18 | forceCompilerAnalyzeBranchHardCodedPtrDereference(false); |
| 20 | } | 19 | } |
test/behavior/math.zig-2| ... | @@ -208,7 +208,6 @@ test "float equality" { | ... | @@ -208,7 +208,6 @@ test "float equality" { |
| 208 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 208 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 209 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 209 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 210 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 210 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 211 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 212 | 211 | ||
| 213 | const x: f64 = 0.012; | 212 | const x: f64 = 0.012; |
| 214 | const y: f64 = x + 1.0; | 213 | const y: f64 = x + 1.0; |
| ... | @@ -684,7 +683,6 @@ test "@addWithOverflow" { | ... | @@ -684,7 +683,6 @@ test "@addWithOverflow" { |
| 684 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 683 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 685 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 684 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 686 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 685 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 687 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 688 | 686 | ||
| 689 | { | 687 | { |
| 690 | var a: u8 = 250; | 688 | var a: u8 = 250; |
test/behavior/maximum_minimum.zig-2| ... | @@ -129,8 +129,6 @@ test "@min/max for floats" { | ... | @@ -129,8 +129,6 @@ test "@min/max for floats" { |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | test "@min/@max on lazy values" { | 131 | test "@min/@max on lazy values" { |
| 132 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 133 | |||
| 134 | const A = extern struct { u8_4: [4]u8 }; | 132 | const A = extern struct { u8_4: [4]u8 }; |
| 135 | const B = extern struct { u8_16: [16]u8 }; | 133 | const B = extern struct { u8_16: [16]u8 }; |
| 136 | const size = @max(@sizeOf(A), @sizeOf(B)); | 134 | const size = @max(@sizeOf(A), @sizeOf(B)); |
test/behavior/memcpy.zig+11-9| ... | @@ -67,14 +67,16 @@ fn testMemcpyDestManyPtr() !void { | ... | @@ -67,14 +67,16 @@ fn testMemcpyDestManyPtr() !void { |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | comptime { | 69 | comptime { |
| 70 | const S = struct { | 70 | if (builtin.zig_backend != .stage2_spirv64) { |
| 71 | buffer: [8]u8 = undefined, | 71 | const S = struct { |
| 72 | fn set(self: *@This(), items: []const u8) void { | 72 | buffer: [8]u8 = undefined, |
| 73 | @memcpy(self.buffer[0..items.len], items); | 73 | fn set(self: *@This(), items: []const u8) void { |
| 74 | } | 74 | @memcpy(self.buffer[0..items.len], items); |
| 75 | }; | 75 | } |
| 76 | }; | ||
| 76 | 77 | ||
| 77 | var s = S{}; | 78 | var s = S{}; |
| 78 | s.set("hello"); | 79 | s.set("hello"); |
| 79 | if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad"); | 80 | if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad"); |
| 81 | } | ||
| 80 | } | 82 | } |
test/behavior/optional.zig-2| ... | @@ -8,7 +8,6 @@ const expectEqualStrings = std.testing.expectEqualStrings; | ... | @@ -8,7 +8,6 @@ const expectEqualStrings = std.testing.expectEqualStrings; |
| 8 | test "passing an optional integer as a parameter" { | 8 | test "passing an optional integer as a parameter" { |
| 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 entry() bool { | 13 | fn entry() bool { |
| ... | @@ -422,7 +421,6 @@ test "optional of noreturn used with orelse" { | ... | @@ -422,7 +421,6 @@ test "optional of noreturn used with orelse" { |
| 422 | } | 421 | } |
| 423 | 422 | ||
| 424 | test "orelse on C pointer" { | 423 | test "orelse on C pointer" { |
| 425 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 426 | 424 | ||
| 427 | // TODO https://github.com/ziglang/zig/issues/6597 | 425 | // TODO https://github.com/ziglang/zig/issues/6597 |
| 428 | const foo: [*c]const u8 = "hey"; | 426 | const foo: [*c]const u8 = "hey"; |
test/behavior/packed-struct.zig-2| ... | @@ -7,7 +7,6 @@ const native_endian = builtin.cpu.arch.endian(); | ... | @@ -7,7 +7,6 @@ const native_endian = builtin.cpu.arch.endian(); |
| 7 | 7 | ||
| 8 | test "flags in packed structs" { | 8 | test "flags in packed structs" { |
| 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 | const Flags1 = packed struct { | 11 | const Flags1 = packed struct { |
| 13 | // first 8 bits | 12 | // first 8 bits |
| ... | @@ -94,7 +93,6 @@ test "flags in packed structs" { | ... | @@ -94,7 +93,6 @@ test "flags in packed structs" { |
| 94 | 93 | ||
| 95 | test "consistent size of packed structs" { | 94 | test "consistent size of packed structs" { |
| 96 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 95 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 97 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 98 | 96 | ||
| 99 | const TxData1 = packed struct { data: u8, _23: u23, full: bool = false }; | 97 | const TxData1 = packed struct { data: u8, _23: u23, full: bool = false }; |
| 100 | const TxData2 = packed struct { data: u9, _22: u22, full: bool = false }; | 98 | const TxData2 = packed struct { data: u9, _22: u22, full: bool = false }; |
test/behavior/pointers.zig-6| ... | @@ -5,7 +5,6 @@ const expect = testing.expect; | ... | @@ -5,7 +5,6 @@ const expect = testing.expect; |
| 5 | const expectError = testing.expectError; | 5 | const expectError = testing.expectError; |
| 6 | 6 | ||
| 7 | test "dereference pointer" { | 7 | test "dereference pointer" { |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | comptime try testDerefPtr(); | 8 | comptime try testDerefPtr(); |
| 10 | try testDerefPtr(); | 9 | try testDerefPtr(); |
| 11 | } | 10 | } |
| ... | @@ -20,7 +19,6 @@ fn testDerefPtr() !void { | ... | @@ -20,7 +19,6 @@ fn testDerefPtr() !void { |
| 20 | test "pointer arithmetic" { | 19 | test "pointer arithmetic" { |
| 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 20 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 22 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 21 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 23 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 24 | 22 | ||
| 25 | var ptr: [*]const u8 = "abcd"; | 23 | var ptr: [*]const u8 = "abcd"; |
| 26 | 24 | ||
| ... | @@ -53,7 +51,6 @@ fn PtrOf(comptime T: type) type { | ... | @@ -53,7 +51,6 @@ fn PtrOf(comptime T: type) type { |
| 53 | 51 | ||
| 54 | test "implicit cast single item pointer to C pointer and back" { | 52 | test "implicit cast single item pointer to C pointer and back" { |
| 55 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 53 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 56 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 57 | 54 | ||
| 58 | var y: u8 = 11; | 55 | var y: u8 = 11; |
| 59 | var x: [*c]u8 = &y; | 56 | var x: [*c]u8 = &y; |
| ... | @@ -70,7 +67,6 @@ test "initialize const optional C pointer to null" { | ... | @@ -70,7 +67,6 @@ test "initialize const optional C pointer to null" { |
| 70 | 67 | ||
| 71 | test "assigning integer to C pointer" { | 68 | test "assigning integer to C pointer" { |
| 72 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 69 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 73 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 74 | 70 | ||
| 75 | var x: i32 = 0; | 71 | var x: i32 = 0; |
| 76 | var y: i32 = 1; | 72 | var y: i32 = 1; |
| ... | @@ -87,7 +83,6 @@ test "assigning integer to C pointer" { | ... | @@ -87,7 +83,6 @@ test "assigning integer to C pointer" { |
| 87 | 83 | ||
| 88 | test "C pointer comparison and arithmetic" { | 84 | test "C pointer comparison and arithmetic" { |
| 89 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 85 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 90 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 91 | 86 | ||
| 92 | const S = struct { | 87 | const S = struct { |
| 93 | fn doTheTest() !void { | 88 | fn doTheTest() !void { |
| ... | @@ -304,7 +299,6 @@ test "null terminated pointer" { | ... | @@ -304,7 +299,6 @@ test "null terminated pointer" { |
| 304 | test "allow any sentinel" { | 299 | test "allow any sentinel" { |
| 305 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 300 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 306 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 301 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 307 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 308 | 302 | ||
| 309 | const S = struct { | 303 | const S = struct { |
| 310 | fn doTheTest() !void { | 304 | fn doTheTest() !void { |
test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig-1| ... | @@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" { | ... | @@ -8,7 +8,6 @@ test "reference a variable in an if after an if in the 2nd switch prong" { |
| 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_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 | try foo(true, Num.Two, false, "aoeu"); | 12 | try foo(true, Num.Two, false, "aoeu"); |
| 14 | try expect(!ok); | 13 | try expect(!ok); |
test/behavior/reflection.zig-1| ... | @@ -28,7 +28,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 { | ... | @@ -28,7 +28,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 { |
| 28 | test "reflection: @field" { | 28 | test "reflection: @field" { |
| 29 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 29 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 30 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 30 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 31 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 32 | 31 | ||
| 33 | var f = Foo{ | 32 | var f = Foo{ |
| 34 | .one = 42, | 33 | .one = 42, |
test/behavior/sizeof_and_typeof.zig-3| ... | @@ -140,8 +140,6 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" { | ... | @@ -140,8 +140,6 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" { |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | test "@TypeOf() has no runtime side effects" { | 142 | test "@TypeOf() has no runtime side effects" { |
| 143 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 144 | |||
| 145 | const S = struct { | 143 | const S = struct { |
| 146 | fn foo(comptime T: type, ptr: *T) T { | 144 | fn foo(comptime T: type, ptr: *T) T { |
| 147 | ptr.* += 1; | 145 | ptr.* += 1; |
| ... | @@ -156,7 +154,6 @@ test "@TypeOf() has no runtime side effects" { | ... | @@ -156,7 +154,6 @@ test "@TypeOf() has no runtime side effects" { |
| 156 | 154 | ||
| 157 | test "branching logic inside @TypeOf" { | 155 | test "branching logic inside @TypeOf" { |
| 158 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 156 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 159 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 160 | 157 | ||
| 161 | const S = struct { | 158 | const S = struct { |
| 162 | var data: i32 = 0; | 159 | var data: i32 = 0; |
test/behavior/slice.zig-3| ... | @@ -200,8 +200,6 @@ test "slicing pointer by length" { | ... | @@ -200,8 +200,6 @@ test "slicing pointer by length" { |
| 200 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | 200 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 201 | const y = x[0x100..]; | 201 | const y = x[0x100..]; |
| 202 | test "compile time slice of pointer to hard coded address" { | 202 | test "compile time slice of pointer to hard coded address" { |
| 203 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 204 | |||
| 205 | try expect(@ptrToInt(x) == 0x1000); | 203 | try expect(@ptrToInt(x) == 0x1000); |
| 206 | try expect(x.len == 0x500); | 204 | try expect(x.len == 0x500); |
| 207 | 205 | ||
| ... | @@ -673,7 +671,6 @@ test "array mult of slice gives ptr to array" { | ... | @@ -673,7 +671,6 @@ test "array mult of slice gives ptr to array" { |
| 673 | 671 | ||
| 674 | test "slice bounds in comptime concatenation" { | 672 | test "slice bounds in comptime concatenation" { |
| 675 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 673 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 676 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 677 | 674 | ||
| 678 | const bs = comptime blk: { | 675 | const bs = comptime blk: { |
| 679 | const b = "........1........"; | 676 | const b = "........1........"; |
test/behavior/struct.zig-3| ... | @@ -11,7 +11,6 @@ top_level_field: i32, | ... | @@ -11,7 +11,6 @@ top_level_field: i32, |
| 11 | test "top level fields" { | 11 | test "top level fields" { |
| 12 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 12 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 14 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 15 | 14 | ||
| 16 | var instance = @This(){ | 15 | var instance = @This(){ |
| 17 | .top_level_field = 1234, | 16 | .top_level_field = 1234, |
| ... | @@ -122,8 +121,6 @@ test "struct byval assign" { | ... | @@ -122,8 +121,6 @@ test "struct byval assign" { |
| 122 | } | 121 | } |
| 123 | 122 | ||
| 124 | test "call struct static method" { | 123 | test "call struct static method" { |
| 125 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 126 | |||
| 127 | const result = StructWithNoFields.add(3, 4); | 124 | const result = StructWithNoFields.add(3, 4); |
| 128 | try expect(result == 7); | 125 | try expect(result == 7); |
| 129 | } | 126 | } |
test/behavior/switch.zig-3| ... | @@ -215,7 +215,6 @@ fn poll() void { | ... | @@ -215,7 +215,6 @@ fn poll() void { |
| 215 | 215 | ||
| 216 | test "switch on global mutable var isn't constant-folded" { | 216 | test "switch on global mutable var isn't constant-folded" { |
| 217 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 217 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 218 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 219 | 218 | ||
| 220 | while (state < 2) { | 219 | while (state < 2) { |
| 221 | poll(); | 220 | poll(); |
| ... | @@ -349,8 +348,6 @@ fn returnsFalse() bool { | ... | @@ -349,8 +348,6 @@ fn returnsFalse() bool { |
| 349 | } | 348 | } |
| 350 | } | 349 | } |
| 351 | test "switch on const enum with var" { | 350 | test "switch on const enum with var" { |
| 352 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 353 | |||
| 354 | try expect(!returnsFalse()); | 351 | try expect(!returnsFalse()); |
| 355 | } | 352 | } |
| 356 | 353 |
test/behavior/this.zig-2| ... | @@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 { | ... | @@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 { |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | test "this refer to module call private fn" { | 23 | test "this refer to module call private fn" { |
| 24 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 25 | |||
| 26 | try expect(module.add(1, 2) == 3); | 24 | try expect(module.add(1, 2) == 3); |
| 27 | } | 25 | } |
| 28 | 26 |
test/behavior/threadlocal.zig-2| ... | @@ -11,7 +11,6 @@ test "thread local variable" { | ... | @@ -11,7 +11,6 @@ test "thread local variable" { |
| 11 | else => return error.SkipZigTest, | 11 | else => return error.SkipZigTest, |
| 12 | }; // TODO | 12 | }; // TODO |
| 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 14 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 15 | 14 | ||
| 16 | const S = struct { | 15 | const S = struct { |
| 17 | threadlocal var t: i32 = 1234; | 16 | threadlocal var t: i32 = 1234; |
| ... | @@ -47,7 +46,6 @@ test "reference a global threadlocal variable" { | ... | @@ -47,7 +46,6 @@ test "reference a global threadlocal variable" { |
| 47 | else => return error.SkipZigTest, | 46 | else => return error.SkipZigTest, |
| 48 | }; // TODO | 47 | }; // TODO |
| 49 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 48 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 50 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 51 | 49 | ||
| 52 | _ = nrfx_uart_rx(&g_uart0); | 50 | _ = nrfx_uart_rx(&g_uart0); |
| 53 | } | 51 | } |
test/behavior/type.zig-1| ... | @@ -491,7 +491,6 @@ test "Type.Fn" { | ... | @@ -491,7 +491,6 @@ test "Type.Fn" { |
| 491 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 491 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 492 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 492 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 493 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 493 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 494 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 495 | 494 | ||
| 496 | const some_opaque = opaque {}; | 495 | const some_opaque = opaque {}; |
| 497 | const some_ptr = *some_opaque; | 496 | const some_ptr = *some_opaque; |
test/behavior/type_info.zig-2| ... | @@ -285,7 +285,6 @@ fn testUnion() !void { | ... | @@ -285,7 +285,6 @@ fn testUnion() !void { |
| 285 | 285 | ||
| 286 | test "type info: struct info" { | 286 | test "type info: struct info" { |
| 287 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 287 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 288 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 289 | 288 | ||
| 290 | try testStruct(); | 289 | try testStruct(); |
| 291 | comptime try testStruct(); | 290 | comptime try testStruct(); |
| ... | @@ -513,7 +512,6 @@ test "type info for async frames" { | ... | @@ -513,7 +512,6 @@ test "type info for async frames" { |
| 513 | 512 | ||
| 514 | test "Declarations are returned in declaration order" { | 513 | test "Declarations are returned in declaration order" { |
| 515 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 514 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 516 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 517 | 515 | ||
| 518 | const S = struct { | 516 | const S = struct { |
| 519 | const a = 1; | 517 | const a = 1; |
test/behavior/undefined.zig-1| ... | @@ -81,7 +81,6 @@ test "assign undefined to struct with method" { | ... | @@ -81,7 +81,6 @@ test "assign undefined to struct with method" { |
| 81 | 81 | ||
| 82 | test "type name of undefined" { | 82 | test "type name of undefined" { |
| 83 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 83 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 84 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 85 | 84 | ||
| 86 | const x = undefined; | 85 | const x = undefined; |
| 87 | try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@TypeOf(undefined)")); | 86 | try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@TypeOf(undefined)")); |
test/behavior/var_args.zig-3| ... | @@ -14,8 +14,6 @@ fn add(args: anytype) i32 { | ... | @@ -14,8 +14,6 @@ fn add(args: anytype) i32 { |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | test "add arbitrary args" { | 16 | test "add arbitrary args" { |
| 17 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 18 | |||
| 19 | try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); | 17 | try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); |
| 20 | try expect(add(.{@as(i32, 1234)}) == 1234); | 18 | try expect(add(.{@as(i32, 1234)}) == 1234); |
| 21 | try expect(add(.{}) == 0); | 19 | try expect(add(.{}) == 0); |
| ... | @@ -32,7 +30,6 @@ test "send void arg to var args" { | ... | @@ -32,7 +30,6 @@ test "send void arg to var args" { |
| 32 | test "pass args directly" { | 30 | test "pass args directly" { |
| 33 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 31 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 34 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 32 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 35 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 36 | 33 | ||
| 37 | try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); | 34 | try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10); |
| 38 | try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234); | 35 | try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234); |
test/behavior/while.zig-3| ... | @@ -5,7 +5,6 @@ const assert = std.debug.assert; | ... | @@ -5,7 +5,6 @@ const assert = std.debug.assert; |
| 5 | 5 | ||
| 6 | test "while loop" { | 6 | test "while loop" { |
| 7 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 7 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 9 | 8 | ||
| 10 | var i: i32 = 0; | 9 | var i: i32 = 0; |
| 11 | while (i < 4) { | 10 | while (i < 4) { |
| ... | @@ -39,8 +38,6 @@ fn staticWhileLoop2() i32 { | ... | @@ -39,8 +38,6 @@ fn staticWhileLoop2() i32 { |
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | test "while with continue expression" { | 40 | test "while with continue expression" { |
| 42 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 43 | |||
| 44 | var sum: i32 = 0; | 41 | var sum: i32 = 0; |
| 45 | { | 42 | { |
| 46 | var i: i32 = 0; | 43 | var i: i32 = 0; |