| author | |
| committer | |
| log | f2835c6a286c9e6bb033cbf04a2ed3463e206bf3 |
| tree | 1a657f52b1ad7d6bee917e2246ad98505cdf69bd |
| parent | 366c76744429cb9c2fcd60abad191b7ef40ed5db |
| parent | 0682c9ac3351b1c7159fd123dc226188918579e6 |
| signature |
Stage2: wasm - Implement unions21 files changed, 211 insertions(+), 64 deletions(-)
src/arch/wasm/CodeGen.zig+118-46| ... | @@ -722,9 +722,9 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | ... | @@ -722,9 +722,9 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 722 | if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64; | 722 | if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64; |
| 723 | break :blk wasm.Valtype.i32; // represented as pointer to stack | 723 | break :blk wasm.Valtype.i32; // represented as pointer to stack |
| 724 | }, | 724 | }, |
| 725 | .Enum => switch (ty.tag()) { | 725 | .Enum => { |
| 726 | .enum_simple => wasm.Valtype.i32, | 726 | var buf: Type.Payload.Bits = undefined; |
| 727 | else => typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty, target), | 727 | return typeToValtype(ty.intTagType(&buf), target); |
| 728 | }, | 728 | }, |
| 729 | else => wasm.Valtype.i32, // all represented as reference/immediate | 729 | else => wasm.Valtype.i32, // all represented as reference/immediate |
| 730 | }; | 730 | }; |
| ... | @@ -1033,14 +1033,21 @@ pub const DeclGen = struct { | ... | @@ -1033,14 +1033,21 @@ pub const DeclGen = struct { |
| 1033 | return Result{ .appended = {} }; | 1033 | return Result{ .appended = {} }; |
| 1034 | }, | 1034 | }, |
| 1035 | .Enum => { | 1035 | .Enum => { |
| 1036 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); | 1036 | var int_buffer: Value.Payload.U64 = undefined; |
| 1037 | return Result{ .appended = {} }; | 1037 | const int_val = val.enumToInt(ty, &int_buffer); |
| 1038 | var buf: Type.Payload.Bits = undefined; | ||
| 1039 | const int_ty = ty.intTagType(&buf); | ||
| 1040 | return self.genTypedValue(int_ty, int_val, writer); | ||
| 1038 | }, | 1041 | }, |
| 1039 | .Bool => { | 1042 | .Bool => { |
| 1040 | try writer.writeByte(@boolToInt(val.toBool())); | 1043 | try writer.writeByte(@boolToInt(val.toBool())); |
| 1041 | return Result{ .appended = {} }; | 1044 | return Result{ .appended = {} }; |
| 1042 | }, | 1045 | }, |
| 1043 | .Struct => { | 1046 | .Struct => { |
| 1047 | const struct_ty = ty.castTag(.@"struct").?.data; | ||
| 1048 | if (struct_ty.layout == .Packed) { | ||
| 1049 | return self.fail("TODO: Packed structs for wasm", .{}); | ||
| 1050 | } | ||
| 1044 | const field_vals = val.castTag(.@"struct").?.data; | 1051 | const field_vals = val.castTag(.@"struct").?.data; |
| 1045 | for (field_vals) |field_val, index| { | 1052 | for (field_vals) |field_val, index| { |
| 1046 | const field_ty = ty.structFieldType(index); | 1053 | const field_ty = ty.structFieldType(index); |
| ... | @@ -1053,9 +1060,45 @@ pub const DeclGen = struct { | ... | @@ -1053,9 +1060,45 @@ pub const DeclGen = struct { |
| 1053 | return Result{ .appended = {} }; | 1060 | return Result{ .appended = {} }; |
| 1054 | }, | 1061 | }, |
| 1055 | .Union => { | 1062 | .Union => { |
| 1056 | // TODO: Implement Union declarations | 1063 | const union_val = val.castTag(.@"union").?.data; |
| 1057 | try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target()))); | 1064 | const layout = ty.unionGetLayout(self.target()); |
| 1058 | return Result{ .appended = {} }; | 1065 | |
| 1066 | if (layout.payload_size == 0) { | ||
| 1067 | return self.genTypedValue(ty.unionTagType().?, union_val.tag, writer); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | // Check if we should store the tag first, in which case, do so now: | ||
| 1071 | if (layout.tag_align >= layout.payload_align) { | ||
| 1072 | switch (try self.genTypedValue(ty.unionTagType().?, union_val.tag, writer)) { | ||
| 1073 | .appended => {}, | ||
| 1074 | .externally_managed => |payload| try writer.writeAll(payload), | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | const union_ty = ty.cast(Type.Payload.Union).?.data; | ||
| 1079 | const field_index = union_ty.tag_ty.enumTagFieldIndex(union_val.tag).?; | ||
| 1080 | assert(union_ty.haveFieldTypes()); | ||
| 1081 | const field_ty = union_ty.fields.values()[field_index].ty; | ||
| 1082 | if (!field_ty.hasRuntimeBits()) { | ||
| 1083 | try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size)); | ||
| 1084 | } else { | ||
| 1085 | switch (try self.genTypedValue(field_ty, union_val.val, writer)) { | ||
| 1086 | .appended => {}, | ||
| 1087 | .externally_managed => |payload| try writer.writeAll(payload), | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | // Unions have the size of the largest field, so we must pad | ||
| 1091 | // whenever the active field has a smaller size. | ||
| 1092 | const diff = layout.payload_size - field_ty.abiSize(self.target()); | ||
| 1093 | if (diff > 0) { | ||
| 1094 | try writer.writeByteNTimes(0xaa, @intCast(usize, diff)); | ||
| 1095 | } | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (layout.tag_size == 0) { | ||
| 1099 | return Result{ .appended = {} }; | ||
| 1100 | } | ||
| 1101 | return self.genTypedValue(union_ty.tag_ty, union_val.tag, writer); | ||
| 1059 | }, | 1102 | }, |
| 1060 | .Pointer => switch (val.tag()) { | 1103 | .Pointer => switch (val.tag()) { |
| 1061 | .variable => { | 1104 | .variable => { |
| ... | @@ -1080,6 +1123,10 @@ pub const DeclGen = struct { | ... | @@ -1080,6 +1123,10 @@ pub const DeclGen = struct { |
| 1080 | } | 1123 | } |
| 1081 | return Result{ .appended = {} }; | 1124 | return Result{ .appended = {} }; |
| 1082 | }, | 1125 | }, |
| 1126 | .zero => { | ||
| 1127 | try writer.writeByteNTimes(0, @divExact(self.target().cpu.arch.ptrBitWidth(), 8)); | ||
| 1128 | return Result{ .appended = {} }; | ||
| 1129 | }, | ||
| 1083 | else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}), | 1130 | else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}), |
| 1084 | }, | 1131 | }, |
| 1085 | .ErrorUnion => { | 1132 | .ErrorUnion => { |
| ... | @@ -1334,7 +1381,7 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1334,7 +1381,7 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1334 | }, | 1381 | }, |
| 1335 | .Pointer => { | 1382 | .Pointer => { |
| 1336 | // Slices act like struct and will be passed by reference | 1383 | // Slices act like struct and will be passed by reference |
| 1337 | if (ty.isSlice()) return ty.hasRuntimeBits(); | 1384 | if (ty.isSlice()) return true; |
| 1338 | return false; | 1385 | return false; |
| 1339 | }, | 1386 | }, |
| 1340 | } | 1387 | } |
| ... | @@ -1394,6 +1441,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1394,6 +1441,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1394 | .bit_or => self.airBinOp(inst, .@"or"), | 1441 | .bit_or => self.airBinOp(inst, .@"or"), |
| 1395 | .bool_and => self.airBinOp(inst, .@"and"), | 1442 | .bool_and => self.airBinOp(inst, .@"and"), |
| 1396 | .bool_or => self.airBinOp(inst, .@"or"), | 1443 | .bool_or => self.airBinOp(inst, .@"or"), |
| 1444 | .rem => self.airBinOp(inst, .rem), | ||
| 1397 | .shl => self.airBinOp(inst, .shl), | 1445 | .shl => self.airBinOp(inst, .shl), |
| 1398 | .shr => self.airBinOp(inst, .shr), | 1446 | .shr => self.airBinOp(inst, .shr), |
| 1399 | .xor => self.airBinOp(inst, .xor), | 1447 | .xor => self.airBinOp(inst, .xor), |
| ... | @@ -1419,6 +1467,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1419,6 +1467,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1419 | .dbg_stmt => WValue.none, | 1467 | .dbg_stmt => WValue.none, |
| 1420 | .intcast => self.airIntcast(inst), | 1468 | .intcast => self.airIntcast(inst), |
| 1421 | .float_to_int => self.airFloatToInt(inst), | 1469 | .float_to_int => self.airFloatToInt(inst), |
| 1470 | .get_union_tag => self.airGetUnionTag(inst), | ||
| 1422 | 1471 | ||
| 1423 | .is_err => self.airIsErr(inst, .i32_ne), | 1472 | .is_err => self.airIsErr(inst, .i32_ne), |
| 1424 | .is_non_err => self.airIsErr(inst, .i32_eq), | 1473 | .is_non_err => self.airIsErr(inst, .i32_eq), |
| ... | @@ -1454,6 +1503,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1454,6 +1503,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1454 | .slice_ptr => self.airSlicePtr(inst), | 1503 | .slice_ptr => self.airSlicePtr(inst), |
| 1455 | .store => self.airStore(inst), | 1504 | .store => self.airStore(inst), |
| 1456 | 1505 | ||
| 1506 | .set_union_tag => self.airSetUnionTag(inst), | ||
| 1457 | .struct_field_ptr => self.airStructFieldPtr(inst), | 1507 | .struct_field_ptr => self.airStructFieldPtr(inst), |
| 1458 | .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0), | 1508 | .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0), |
| 1459 | .struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1), | 1509 | .struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1), |
| ... | @@ -1477,7 +1527,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1477,7 +1527,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1477 | .div_float, | 1527 | .div_float, |
| 1478 | .div_floor, | 1528 | .div_floor, |
| 1479 | .div_exact, | 1529 | .div_exact, |
| 1480 | .rem, | ||
| 1481 | .mod, | 1530 | .mod, |
| 1482 | .max, | 1531 | .max, |
| 1483 | .min, | 1532 | .min, |
| ... | @@ -1494,8 +1543,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1494,8 +1543,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1494 | .fpext, | 1543 | .fpext, |
| 1495 | .unwrap_errunion_payload_ptr, | 1544 | .unwrap_errunion_payload_ptr, |
| 1496 | .unwrap_errunion_err_ptr, | 1545 | .unwrap_errunion_err_ptr, |
| 1497 | .set_union_tag, | 1546 | |
| 1498 | .get_union_tag, | ||
| 1499 | .ptr_slice_len_ptr, | 1547 | .ptr_slice_len_ptr, |
| 1500 | .ptr_slice_ptr_ptr, | 1548 | .ptr_slice_ptr_ptr, |
| 1501 | .int_to_float, | 1549 | .int_to_float, |
| ... | @@ -1518,7 +1566,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1518,7 +1566,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1518 | .sub_with_overflow, | 1566 | .sub_with_overflow, |
| 1519 | .mul_with_overflow, | 1567 | .mul_with_overflow, |
| 1520 | .shl_with_overflow, | 1568 | .shl_with_overflow, |
| 1521 | => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), | 1569 | => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1522 | }; | 1570 | }; |
| 1523 | } | 1571 | } |
| 1524 | 1572 | ||
| ... | @@ -1596,6 +1644,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -1596,6 +1644,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1596 | break :blk func.data.owner_decl; | 1644 | break :blk func.data.owner_decl; |
| 1597 | } else if (func_val.castTag(.extern_fn)) |ext_fn| { | 1645 | } else if (func_val.castTag(.extern_fn)) |ext_fn| { |
| 1598 | break :blk ext_fn.data; | 1646 | break :blk ext_fn.data; |
| 1647 | } else if (func_val.castTag(.decl_ref)) |decl_ref| { | ||
| 1648 | break :blk decl_ref.data; | ||
| 1599 | } | 1649 | } |
| 1600 | return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()}); | 1650 | return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()}); |
| 1601 | }; | 1651 | }; |
| ... | @@ -1697,7 +1747,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1697,7 +1747,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1697 | 1747 | ||
| 1698 | return self.memCopy(ty, lhs, rhs); | 1748 | return self.memCopy(ty, lhs, rhs); |
| 1699 | }, | 1749 | }, |
| 1700 | .Struct, .Array => { | 1750 | .Struct, .Array, .Union => { |
| 1701 | return try self.memCopy(ty, lhs, rhs); | 1751 | return try self.memCopy(ty, lhs, rhs); |
| 1702 | }, | 1752 | }, |
| 1703 | .Pointer => { | 1753 | .Pointer => { |
| ... | @@ -1720,18 +1770,8 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1720,18 +1770,8 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1720 | try self.emitWValue(lhs); | 1770 | try self.emitWValue(lhs); |
| 1721 | try self.emitWValue(rhs); | 1771 | try self.emitWValue(rhs); |
| 1722 | const valtype = typeToValtype(ty, self.target); | 1772 | const valtype = typeToValtype(ty, self.target); |
| 1723 | // check if we should pass by pointer or value based on ABI size | 1773 | const abi_size = @intCast(u8, ty.abiSize(self.target)); |
| 1724 | // TODO: Implement a way to get ABI values from a given type, | 1774 | |
| 1725 | // that is portable across the backend, rather than copying logic. | ||
| 1726 | const abi_size = switch (ty.zigTypeTag()) { | ||
| 1727 | .Int, | ||
| 1728 | .Float, | ||
| 1729 | .ErrorSet, | ||
| 1730 | .Enum, | ||
| 1731 | .Bool, | ||
| 1732 | => @intCast(u8, ty.abiSize(self.target)), | ||
| 1733 | else => @as(u8, 4), | ||
| 1734 | }; | ||
| 1735 | const opcode = buildOpcode(.{ | 1775 | const opcode = buildOpcode(.{ |
| 1736 | .valtype1 = valtype, | 1776 | .valtype1 = valtype, |
| 1737 | .width = abi_size * 8, // use bitsize instead of byte size | 1777 | .width = abi_size * 8, // use bitsize instead of byte size |
| ... | @@ -1771,22 +1811,9 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue { | ... | @@ -1771,22 +1811,9 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue { |
| 1771 | .unsigned | 1811 | .unsigned |
| 1772 | else | 1812 | else |
| 1773 | .signed; | 1813 | .signed; |
| 1774 | // TODO: Implement a way to get ABI values from a given type, | 1814 | |
| 1775 | // that is portable across the backend, rather than copying logic. | 1815 | // TODO: Revisit below to determine if optional zero-sized pointers should still have abi-size 4. |
| 1776 | const abi_size = switch (ty.zigTypeTag()) { | 1816 | const abi_size = if (ty.isPtrLikeOptional()) @as(u8, 4) else @intCast(u8, ty.abiSize(self.target)); |
| 1777 | .Int, | ||
| 1778 | .Float, | ||
| 1779 | .ErrorSet, | ||
| 1780 | .Enum, | ||
| 1781 | .Bool, | ||
| 1782 | .ErrorUnion, | ||
| 1783 | => @intCast(u8, ty.abiSize(self.target)), | ||
| 1784 | .Optional => blk: { | ||
| 1785 | if (ty.isPtrLikeOptional()) break :blk @intCast(u8, self.ptrSize()); | ||
| 1786 | break :blk @intCast(u8, ty.abiSize(self.target)); | ||
| 1787 | }, | ||
| 1788 | else => @as(u8, 4), | ||
| 1789 | }; | ||
| 1790 | 1817 | ||
| 1791 | const opcode = buildOpcode(.{ | 1818 | const opcode = buildOpcode(.{ |
| 1792 | .valtype1 = typeToValtype(ty, self.target), | 1819 | .valtype1 = typeToValtype(ty, self.target), |
| ... | @@ -1952,7 +1979,13 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { | ... | @@ -1952,7 +1979,13 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 1952 | return WValue{ .imm32 = field_index.data }; | 1979 | return WValue{ .imm32 = field_index.data }; |
| 1953 | } | 1980 | } |
| 1954 | }, | 1981 | }, |
| 1955 | else => unreachable, | 1982 | .enum_numbered => { |
| 1983 | const index = field_index.data; | ||
| 1984 | const enum_data = ty.castTag(.enum_numbered).?.data; | ||
| 1985 | const enum_val = enum_data.values.keys()[index]; | ||
| 1986 | return self.lowerConstant(enum_val, enum_data.tag_ty); | ||
| 1987 | }, | ||
| 1988 | else => return self.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}), | ||
| 1956 | } | 1989 | } |
| 1957 | } else { | 1990 | } else { |
| 1958 | var int_tag_buffer: Type.Payload.Bits = undefined; | 1991 | var int_tag_buffer: Type.Payload.Bits = undefined; |
| ... | @@ -2724,7 +2757,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2724,7 +2757,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2724 | const elem_size = elem_ty.abiSize(self.target); | 2757 | const elem_size = elem_ty.abiSize(self.target); |
| 2725 | 2758 | ||
| 2726 | // load pointer onto stack | 2759 | // load pointer onto stack |
| 2727 | const slice_ptr = try self.load(slice, slice_ty, 0); | 2760 | const slice_ptr = try self.load(slice, Type.usize, 0); |
| 2728 | try self.addLabel(.local_get, slice_ptr.local); | 2761 | try self.addLabel(.local_get, slice_ptr.local); |
| 2729 | 2762 | ||
| 2730 | // calculate index into slice | 2763 | // calculate index into slice |
| ... | @@ -2746,14 +2779,13 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2746,14 +2779,13 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2746 | if (self.liveness.isUnused(inst)) return WValue.none; | 2779 | if (self.liveness.isUnused(inst)) return WValue.none; |
| 2747 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 2780 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2748 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2781 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2749 | const slice_ty = self.air.typeOf(bin_op.lhs); | ||
| 2750 | const elem_ty = self.air.getRefType(ty_pl.ty).childType(); | 2782 | const elem_ty = self.air.getRefType(ty_pl.ty).childType(); |
| 2751 | const elem_size = elem_ty.abiSize(self.target); | 2783 | const elem_size = elem_ty.abiSize(self.target); |
| 2752 | 2784 | ||
| 2753 | const slice = try self.resolveInst(bin_op.lhs); | 2785 | const slice = try self.resolveInst(bin_op.lhs); |
| 2754 | const index = try self.resolveInst(bin_op.rhs); | 2786 | const index = try self.resolveInst(bin_op.rhs); |
| 2755 | 2787 | ||
| 2756 | const slice_ptr = try self.load(slice, slice_ty, 0); | 2788 | const slice_ptr = try self.load(slice, Type.usize, 0); |
| 2757 | try self.addLabel(.local_get, slice_ptr.local); | 2789 | try self.addLabel(.local_get, slice_ptr.local); |
| 2758 | 2790 | ||
| 2759 | // calculate index into slice | 2791 | // calculate index into slice |
| ... | @@ -3177,3 +3209,43 @@ fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.ma | ... | @@ -3177,3 +3209,43 @@ fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.ma |
| 3177 | try self.addLabel(.local_set, result.local); | 3209 | try self.addLabel(.local_set, result.local); |
| 3178 | return result; | 3210 | return result; |
| 3179 | } | 3211 | } |
| 3212 | |||
| 3213 | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ||
| 3214 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | ||
| 3215 | const un_ty = self.air.typeOf(bin_op.lhs).childType(); | ||
| 3216 | const tag_ty = self.air.typeOf(bin_op.rhs); | ||
| 3217 | const layout = un_ty.unionGetLayout(self.target); | ||
| 3218 | if (layout.tag_size == 0) return WValue{ .none = {} }; | ||
| 3219 | const union_ptr = try self.resolveInst(bin_op.lhs); | ||
| 3220 | const new_tag = try self.resolveInst(bin_op.rhs); | ||
| 3221 | if (layout.payload_size == 0) { | ||
| 3222 | try self.store(union_ptr, new_tag, tag_ty, 0); | ||
| 3223 | return WValue{ .none = {} }; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | // when the tag alignment is smaller than the payload, the field will be stored | ||
| 3227 | // after the payload. | ||
| 3228 | const offset = if (layout.tag_align < layout.payload_align) blk: { | ||
| 3229 | break :blk @intCast(u32, layout.payload_size); | ||
| 3230 | } else @as(u32, 0); | ||
| 3231 | try self.store(union_ptr, new_tag, tag_ty, offset); | ||
| 3232 | return WValue{ .none = {} }; | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ||
| 3236 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; | ||
| 3237 | |||
| 3238 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 3239 | const un_ty = self.air.typeOf(ty_op.operand); | ||
| 3240 | const tag_ty = self.air.typeOfIndex(inst); | ||
| 3241 | const layout = un_ty.unionGetLayout(self.target); | ||
| 3242 | if (layout.tag_size == 0) return WValue{ .none = {} }; | ||
| 3243 | const operand = try self.resolveInst(ty_op.operand); | ||
| 3244 | |||
| 3245 | // when the tag alignment is smaller than the payload, the field will be stored | ||
| 3246 | // after the payload. | ||
| 3247 | const offset = if (layout.tag_align < layout.payload_align) blk: { | ||
| 3248 | break :blk @intCast(u32, layout.payload_size); | ||
| 3249 | } else @as(u32, 0); | ||
| 3250 | return self.load(operand, tag_ty, offset); | ||
| 3251 | } |
src/arch/wasm/Emit.zig+4| ... | @@ -173,6 +173,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -173,6 +173,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 173 | .i64_trunc_f32_u => try emit.emitTag(tag), | 173 | .i64_trunc_f32_u => try emit.emitTag(tag), |
| 174 | .i64_trunc_f64_s => try emit.emitTag(tag), | 174 | .i64_trunc_f64_s => try emit.emitTag(tag), |
| 175 | .i64_trunc_f64_u => try emit.emitTag(tag), | 175 | .i64_trunc_f64_u => try emit.emitTag(tag), |
| 176 | .i32_rem_s => try emit.emitTag(tag), | ||
| 177 | .i32_rem_u => try emit.emitTag(tag), | ||
| 178 | .i64_rem_s => try emit.emitTag(tag), | ||
| 179 | .i64_rem_u => try emit.emitTag(tag), | ||
| 176 | 180 | ||
| 177 | .extended => try emit.emitExtended(inst), | 181 | .extended => try emit.emitExtended(inst), |
| 178 | } | 182 | } |
src/arch/wasm/Mir.zig+8| ... | @@ -327,6 +327,10 @@ pub const Inst = struct { | ... | @@ -327,6 +327,10 @@ pub const Inst = struct { |
| 327 | /// Uses `tag` | 327 | /// Uses `tag` |
| 328 | i32_div_u = 0x6E, | 328 | i32_div_u = 0x6E, |
| 329 | /// Uses `tag` | 329 | /// Uses `tag` |
| 330 | i32_rem_s = 0x6F, | ||
| 331 | /// Uses `tag` | ||
| 332 | i32_rem_u = 0x70, | ||
| 333 | /// Uses `tag` | ||
| 330 | i32_and = 0x71, | 334 | i32_and = 0x71, |
| 331 | /// Uses `tag` | 335 | /// Uses `tag` |
| 332 | i32_or = 0x72, | 336 | i32_or = 0x72, |
| ... | @@ -349,6 +353,10 @@ pub const Inst = struct { | ... | @@ -349,6 +353,10 @@ pub const Inst = struct { |
| 349 | /// Uses `tag` | 353 | /// Uses `tag` |
| 350 | i64_div_u = 0x80, | 354 | i64_div_u = 0x80, |
| 351 | /// Uses `tag` | 355 | /// Uses `tag` |
| 356 | i64_rem_s = 0x81, | ||
| 357 | /// Uses `tag` | ||
| 358 | i64_rem_u = 0x82, | ||
| 359 | /// Uses `tag` | ||
| 352 | i64_and = 0x83, | 360 | i64_and = 0x83, |
| 353 | /// Uses `tag` | 361 | /// Uses `tag` |
| 354 | i64_or = 0x84, | 362 | i64_or = 0x84, |
test/behavior.zig+17-17| ... | @@ -3,18 +3,34 @@ const builtin = @import("builtin"); | ... | @@ -3,18 +3,34 @@ const builtin = @import("builtin"); |
| 3 | test { | 3 | test { |
| 4 | // Tests that pass for stage1, llvm backend, C backend, wasm backend, arm backend and x86_64 backend. | 4 | // Tests that pass for stage1, llvm backend, C backend, wasm backend, arm backend and x86_64 backend. |
| 5 | _ = @import("behavior/align.zig"); | 5 | _ = @import("behavior/align.zig"); |
| 6 | _ = @import("behavior/alignof.zig"); | ||
| 6 | _ = @import("behavior/array.zig"); | 7 | _ = @import("behavior/array.zig"); |
| 8 | _ = @import("behavior/bit_shifting.zig"); | ||
| 7 | _ = @import("behavior/bool.zig"); | 9 | _ = @import("behavior/bool.zig"); |
| 10 | _ = @import("behavior/bugs/394.zig"); | ||
| 8 | _ = @import("behavior/bugs/655.zig"); | 11 | _ = @import("behavior/bugs/655.zig"); |
| 12 | _ = @import("behavior/bugs/656.zig"); | ||
| 9 | _ = @import("behavior/bugs/679.zig"); | 13 | _ = @import("behavior/bugs/679.zig"); |
| 10 | _ = @import("behavior/bugs/1111.zig"); | 14 | _ = @import("behavior/bugs/1111.zig"); |
| 15 | _ = @import("behavior/bugs/1277.zig"); | ||
| 16 | _ = @import("behavior/bugs/1310.zig"); | ||
| 17 | _ = @import("behavior/bugs/1381.zig"); | ||
| 18 | _ = @import("behavior/bugs/1500.zig"); | ||
| 19 | _ = @import("behavior/bugs/1735.zig"); | ||
| 20 | _ = @import("behavior/bugs/2006.zig"); | ||
| 11 | _ = @import("behavior/bugs/2346.zig"); | 21 | _ = @import("behavior/bugs/2346.zig"); |
| 22 | _ = @import("behavior/bugs/3112.zig"); | ||
| 23 | _ = @import("behavior/bugs/3367.zig"); | ||
| 12 | _ = @import("behavior/bugs/6850.zig"); | 24 | _ = @import("behavior/bugs/6850.zig"); |
| 25 | _ = @import("behavior/bugs/7250.zig"); | ||
| 13 | _ = @import("behavior/cast.zig"); | 26 | _ = @import("behavior/cast.zig"); |
| 14 | _ = @import("behavior/comptime_memory.zig"); | 27 | _ = @import("behavior/comptime_memory.zig"); |
| 15 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | 28 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); |
| 29 | _ = @import("behavior/generics_llvm.zig"); | ||
| 16 | _ = @import("behavior/hasdecl.zig"); | 30 | _ = @import("behavior/hasdecl.zig"); |
| 17 | _ = @import("behavior/hasfield.zig"); | 31 | _ = @import("behavior/hasfield.zig"); |
| 32 | _ = @import("behavior/namespace_depends_on_compile_var.zig"); | ||
| 33 | _ = @import("behavior/optional_llvm.zig"); | ||
| 18 | _ = @import("behavior/prefetch.zig"); | 34 | _ = @import("behavior/prefetch.zig"); |
| 19 | _ = @import("behavior/pub_enum.zig"); | 35 | _ = @import("behavior/pub_enum.zig"); |
| 20 | _ = @import("behavior/slice_sentinel_comptime.zig"); | 36 | _ = @import("behavior/slice_sentinel_comptime.zig"); |
| ... | @@ -60,6 +76,7 @@ test { | ... | @@ -60,6 +76,7 @@ test { |
| 60 | _ = @import("behavior/type_info.zig"); | 76 | _ = @import("behavior/type_info.zig"); |
| 61 | _ = @import("behavior/undefined.zig"); | 77 | _ = @import("behavior/undefined.zig"); |
| 62 | _ = @import("behavior/underscore.zig"); | 78 | _ = @import("behavior/underscore.zig"); |
| 79 | _ = @import("behavior/union.zig"); | ||
| 63 | _ = @import("behavior/usingnamespace.zig"); | 80 | _ = @import("behavior/usingnamespace.zig"); |
| 64 | _ = @import("behavior/void.zig"); | 81 | _ = @import("behavior/void.zig"); |
| 65 | _ = @import("behavior/while.zig"); | 82 | _ = @import("behavior/while.zig"); |
| ... | @@ -68,30 +85,16 @@ test { | ... | @@ -68,30 +85,16 @@ test { |
| 68 | // Tests that pass for stage1, llvm backend, C backend | 85 | // Tests that pass for stage1, llvm backend, C backend |
| 69 | _ = @import("behavior/cast_int.zig"); | 86 | _ = @import("behavior/cast_int.zig"); |
| 70 | _ = @import("behavior/int128.zig"); | 87 | _ = @import("behavior/int128.zig"); |
| 71 | _ = @import("behavior/union.zig"); | ||
| 72 | _ = @import("behavior/translate_c_macros.zig"); | 88 | _ = @import("behavior/translate_c_macros.zig"); |
| 73 | 89 | ||
| 74 | if (builtin.zig_backend != .stage2_c) { | 90 | if (builtin.zig_backend != .stage2_c) { |
| 75 | // Tests that pass for stage1 and the llvm backend. | 91 | // Tests that pass for stage1 and the llvm backend. |
| 76 | _ = @import("behavior/alignof.zig"); | ||
| 77 | _ = @import("behavior/array_llvm.zig"); | 92 | _ = @import("behavior/array_llvm.zig"); |
| 78 | _ = @import("behavior/atomics.zig"); | 93 | _ = @import("behavior/atomics.zig"); |
| 79 | _ = @import("behavior/basic_llvm.zig"); | 94 | _ = @import("behavior/basic_llvm.zig"); |
| 80 | _ = @import("behavior/bit_shifting.zig"); | ||
| 81 | _ = @import("behavior/bugs/394.zig"); | ||
| 82 | _ = @import("behavior/bugs/656.zig"); | ||
| 83 | _ = @import("behavior/bugs/1277.zig"); | ||
| 84 | _ = @import("behavior/bugs/1310.zig"); | ||
| 85 | _ = @import("behavior/bugs/1381.zig"); | ||
| 86 | _ = @import("behavior/bugs/1500.zig"); | ||
| 87 | _ = @import("behavior/bugs/1735.zig"); | ||
| 88 | _ = @import("behavior/bugs/1741.zig"); | 95 | _ = @import("behavior/bugs/1741.zig"); |
| 89 | _ = @import("behavior/bugs/2006.zig"); | ||
| 90 | _ = @import("behavior/bugs/2578.zig"); | 96 | _ = @import("behavior/bugs/2578.zig"); |
| 91 | _ = @import("behavior/bugs/3007.zig"); | 97 | _ = @import("behavior/bugs/3007.zig"); |
| 92 | _ = @import("behavior/bugs/3112.zig"); | ||
| 93 | _ = @import("behavior/bugs/3367.zig"); | ||
| 94 | _ = @import("behavior/bugs/7250.zig"); | ||
| 95 | _ = @import("behavior/bugs/9584.zig"); | 98 | _ = @import("behavior/bugs/9584.zig"); |
| 96 | _ = @import("behavior/cast_llvm.zig"); | 99 | _ = @import("behavior/cast_llvm.zig"); |
| 97 | _ = @import("behavior/enum_llvm.zig"); | 100 | _ = @import("behavior/enum_llvm.zig"); |
| ... | @@ -99,13 +102,10 @@ test { | ... | @@ -99,13 +102,10 @@ test { |
| 99 | _ = @import("behavior/eval.zig"); | 102 | _ = @import("behavior/eval.zig"); |
| 100 | _ = @import("behavior/floatop.zig"); | 103 | _ = @import("behavior/floatop.zig"); |
| 101 | _ = @import("behavior/fn.zig"); | 104 | _ = @import("behavior/fn.zig"); |
| 102 | _ = @import("behavior/generics_llvm.zig"); | ||
| 103 | _ = @import("behavior/math.zig"); | 105 | _ = @import("behavior/math.zig"); |
| 104 | _ = @import("behavior/maximum_minimum.zig"); | 106 | _ = @import("behavior/maximum_minimum.zig"); |
| 105 | _ = @import("behavior/merge_error_sets.zig"); | 107 | _ = @import("behavior/merge_error_sets.zig"); |
| 106 | _ = @import("behavior/namespace_depends_on_compile_var.zig"); | ||
| 107 | _ = @import("behavior/null_llvm.zig"); | 108 | _ = @import("behavior/null_llvm.zig"); |
| 108 | _ = @import("behavior/optional_llvm.zig"); | ||
| 109 | _ = @import("behavior/popcount.zig"); | 109 | _ = @import("behavior/popcount.zig"); |
| 110 | _ = @import("behavior/saturating_arithmetic.zig"); | 110 | _ = @import("behavior/saturating_arithmetic.zig"); |
| 111 | _ = @import("behavior/sizeof_and_typeof.zig"); | 111 | _ = @import("behavior/sizeof_and_typeof.zig"); |
test/behavior/alignof.zig+6| ... | @@ -11,6 +11,9 @@ const Foo = struct { | ... | @@ -11,6 +11,9 @@ const Foo = struct { |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | test "@alignOf(T) before referencing T" { | 13 | test "@alignOf(T) before referencing T" { |
| 14 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 15 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 16 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 14 | comptime try expect(@alignOf(Foo) != maxInt(usize)); | 17 | comptime try expect(@alignOf(Foo) != maxInt(usize)); |
| 15 | if (native_arch == .x86_64) { | 18 | if (native_arch == .x86_64) { |
| 16 | comptime try expect(@alignOf(Foo) == 4); | 19 | comptime try expect(@alignOf(Foo) == 4); |
| ... | @@ -18,6 +21,9 @@ test "@alignOf(T) before referencing T" { | ... | @@ -18,6 +21,9 @@ test "@alignOf(T) before referencing T" { |
| 18 | } | 21 | } |
| 19 | 22 | ||
| 20 | test "comparison of @alignOf(T) against zero" { | 23 | test "comparison of @alignOf(T) against zero" { |
| 24 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 25 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 26 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 21 | { | 27 | { |
| 22 | const T = struct { x: u32 }; | 28 | const T = struct { x: u32 }; |
| 23 | try expect(!(@alignOf(T) == 0)); | 29 | try expect(!(@alignOf(T) == 0)); |
test/behavior/bit_shifting.zig+4| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const builtin = @import("builtin"); | ||
| 3 | 4 | ||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | 5 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { |
| 5 | const key_bits = @typeInfo(Key).Int.bits; | 6 | const key_bits = @typeInfo(Key).Int.bits; |
| ... | @@ -60,6 +61,9 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt | ... | @@ -60,6 +61,9 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | test "sharded table" { | 63 | test "sharded table" { |
| 64 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 65 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 66 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 63 | // realistic 16-way sharding | 67 | // realistic 16-way sharding |
| 64 | try testShardedTable(u32, 4, 8); | 68 | try testShardedTable(u32, 4, 8); |
| 65 | 69 |
test/behavior/bugs/1277.zig+3| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | const S = struct { | 4 | const S = struct { |
| 4 | f: ?fn () i32, | 5 | f: ?fn () i32, |
| ... | @@ -11,5 +12,7 @@ fn f() i32 { | ... | @@ -11,5 +12,7 @@ fn f() i32 { |
| 11 | } | 12 | } |
| 12 | 13 | ||
| 13 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { | 14 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { |
| 15 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 16 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 14 | try std.testing.expect(s.f.?() == 1234); | 17 | try std.testing.expect(s.f.?() == 1234); |
| 15 | } | 18 | } |
test/behavior/bugs/1310.zig+3| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const builtin = @import("builtin"); | ||
| 3 | 4 | ||
| 4 | pub const VM = ?[*]const struct_InvocationTable_; | 5 | pub const VM = ?[*]const struct_InvocationTable_; |
| 5 | pub const struct_InvocationTable_ = extern struct { | 6 | pub const struct_InvocationTable_ = extern struct { |
| ... | @@ -22,5 +23,7 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 { | ... | @@ -22,5 +23,7 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 { |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | test "fixed" { | 25 | test "fixed" { |
| 26 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 27 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 25 | try expect(agent_callback(undefined, undefined) == 11); | 28 | try expect(agent_callback(undefined, undefined) == 11); |
| 26 | } | 29 | } |
test/behavior/bugs/1381.zig+3| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | const B = union(enum) { | 4 | const B = union(enum) { |
| 4 | D: u8, | 5 | D: u8, |
| ... | @@ -11,6 +12,8 @@ const A = union(enum) { | ... | @@ -11,6 +12,8 @@ const A = union(enum) { |
| 11 | }; | 12 | }; |
| 12 | 13 | ||
| 13 | test "union that needs padding bytes inside an array" { | 14 | test "union that needs padding bytes inside an array" { |
| 15 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 16 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 14 | var as = [_]A{ | 17 | var as = [_]A{ |
| 15 | A{ .B = B{ .D = 1 } }, | 18 | A{ .B = B{ .D = 1 } }, |
| 16 | A{ .B = B{ .D = 1 } }, | 19 | A{ .B = B{ .D = 1 } }, |
test/behavior/bugs/1500.zig+4| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const A = struct { | 2 | const A = struct { |
| 2 | b: B, | 3 | b: B, |
| 3 | }; | 4 | }; |
| ... | @@ -5,6 +6,9 @@ const A = struct { | ... | @@ -5,6 +6,9 @@ const A = struct { |
| 5 | const B = *const fn (A) void; | 6 | const B = *const fn (A) void; |
| 6 | 7 | ||
| 7 | test "allow these dependencies" { | 8 | test "allow these dependencies" { |
| 9 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 11 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 8 | var a: A = undefined; | 12 | var a: A = undefined; |
| 9 | var b: B = undefined; | 13 | var b: B = undefined; |
| 10 | if (false) { | 14 | if (false) { |
test/behavior/bugs/1735.zig+4| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | const mystruct = struct { | 4 | const mystruct = struct { |
| 4 | pending: ?listofstructs, | 5 | pending: ?listofstructs, |
| ... | @@ -41,6 +42,9 @@ const a = struct { | ... | @@ -41,6 +42,9 @@ const a = struct { |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | test "initialization" { | 44 | test "initialization" { |
| 45 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 46 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 47 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 44 | var t = a.init(); | 48 | var t = a.init(); |
| 45 | try std.testing.expect(t.foo.len == 0); | 49 | try std.testing.expect(t.foo.len == 0); |
| 46 | } | 50 | } |
test/behavior/bugs/2006.zig+4| ... | @@ -1,10 +1,14 @@ | ... | @@ -1,10 +1,14 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const builtin = @import("builtin"); | ||
| 3 | 4 | ||
| 4 | const S = struct { | 5 | const S = struct { |
| 5 | p: *S, | 6 | p: *S, |
| 6 | }; | 7 | }; |
| 7 | test "bug 2006" { | 8 | test "bug 2006" { |
| 9 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 11 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 8 | var a: S = undefined; | 12 | var a: S = undefined; |
| 9 | a = S{ .p = undefined }; | 13 | a = S{ .p = undefined }; |
| 10 | try expect(@sizeOf(S) != 0); | 14 | try expect(@sizeOf(S) != 0); |
test/behavior/bugs/3112.zig+3-1| ... | @@ -13,7 +13,9 @@ fn prev(p: ?State) void { | ... | @@ -13,7 +13,9 @@ fn prev(p: ?State) void { |
| 13 | 13 | ||
| 14 | test "zig test crash" { | 14 | test "zig test crash" { |
| 15 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 15 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 16 | 16 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 17 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 18 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 17 | var global: State = undefined; | 19 | var global: State = undefined; |
| 18 | global.enter = prev; | 20 | global.enter = prev; |
| 19 | global.enter(null); | 21 | global.enter(null); |
test/behavior/bugs/3367.zig+4| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const Foo = struct { | 2 | const Foo = struct { |
| 2 | usingnamespace Mixin; | 3 | usingnamespace Mixin; |
| 3 | }; | 4 | }; |
| ... | @@ -9,6 +10,9 @@ const Mixin = struct { | ... | @@ -9,6 +10,9 @@ const Mixin = struct { |
| 9 | }; | 10 | }; |
| 10 | 11 | ||
| 11 | test "container member access usingnamespace decls" { | 12 | test "container member access usingnamespace decls" { |
| 13 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 14 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 15 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 12 | var foo = Foo{}; | 16 | var foo = Foo{}; |
| 13 | foo.two(); | 17 | foo.two(); |
| 14 | } | 18 | } |
test/behavior/bugs/394.zig+3| ... | @@ -8,8 +8,11 @@ const S = struct { | ... | @@ -8,8 +8,11 @@ const S = struct { |
| 8 | }; | 8 | }; |
| 9 | 9 | ||
| 10 | const expect = @import("std").testing.expect; | 10 | const expect = @import("std").testing.expect; |
| 11 | const builtin = @import("builtin"); | ||
| 11 | 12 | ||
| 12 | test "bug 394 fixed" { | 13 | test "bug 394 fixed" { |
| 14 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 15 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 13 | const x = S{ | 16 | const x = S{ |
| 14 | .x = 3, | 17 | .x = 3, |
| 15 | .y = E{ .B = 1 }, | 18 | .y = E{ .B = 1 }, |
test/behavior/bugs/656.zig+3| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const expect = @import("std").testing.expect; | 1 | const expect = @import("std").testing.expect; |
| 2 | const builtin = @import("builtin"); | ||
| 2 | 3 | ||
| 3 | const PrefixOp = union(enum) { | 4 | const PrefixOp = union(enum) { |
| 4 | Return, | 5 | Return, |
| ... | @@ -10,6 +11,8 @@ const Value = struct { | ... | @@ -10,6 +11,8 @@ const Value = struct { |
| 10 | }; | 11 | }; |
| 11 | 12 | ||
| 12 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | 13 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { |
| 14 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 15 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 13 | try foo(false, true); | 16 | try foo(false, true); |
| 14 | } | 17 | } |
| 15 | 18 |
test/behavior/bugs/7250.zig+4| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const nrfx_uart_t = extern struct { | 2 | const nrfx_uart_t = extern struct { |
| 2 | p_reg: [*c]u32, | 3 | p_reg: [*c]u32, |
| 3 | drv_inst_idx: u8, | 4 | drv_inst_idx: u8, |
| ... | @@ -13,5 +14,8 @@ threadlocal var g_uart0 = nrfx_uart_t{ | ... | @@ -13,5 +14,8 @@ threadlocal var g_uart0 = nrfx_uart_t{ |
| 13 | }; | 14 | }; |
| 14 | 15 | ||
| 15 | test "reference a global threadlocal variable" { | 16 | test "reference a global threadlocal variable" { |
| 17 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 18 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 19 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 16 | _ = nrfx_uart_rx(&g_uart0); | 20 | _ = nrfx_uart_rx(&g_uart0); |
| 17 | } | 21 | } |
test/behavior/generics_llvm.zig+7| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const builtin = @import("builtin"); | ||
| 3 | 4 | ||
| 4 | const foos = [_]fn (anytype) bool{ | 5 | const foos = [_]fn (anytype) bool{ |
| 5 | foo1, | 6 | foo1, |
| ... | @@ -14,11 +15,17 @@ fn foo2(arg: anytype) bool { | ... | @@ -14,11 +15,17 @@ fn foo2(arg: anytype) bool { |
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | test "array of generic fns" { | 17 | test "array of generic fns" { |
| 18 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 19 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 20 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 17 | try expect(foos[0](true)); | 21 | try expect(foos[0](true)); |
| 18 | try expect(!foos[1](true)); | 22 | try expect(!foos[1](true)); |
| 19 | } | 23 | } |
| 20 | 24 | ||
| 21 | test "generic struct" { | 25 | test "generic struct" { |
| 26 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 27 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 28 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 22 | var a1 = GenNode(i32){ | 29 | var a1 = GenNode(i32){ |
| 23 | .value = 13, | 30 | .value = 13, |
| 24 | .next = null, | 31 | .next = null, |
test/behavior/namespace_depends_on_compile_var.zig+3| ... | @@ -3,6 +3,9 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,9 @@ const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | test "namespace depends on compile var" { | 5 | test "namespace depends on compile var" { |
| 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 8 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 6 | if (some_namespace.a_bool) { | 9 | if (some_namespace.a_bool) { |
| 7 | try expect(some_namespace.a_bool); | 10 | try expect(some_namespace.a_bool); |
| 8 | } else { | 11 | } else { |
test/behavior/optional_llvm.zig+4| ... | @@ -2,8 +2,12 @@ const std = @import("std"); | ... | @@ -2,8 +2,12 @@ const std = @import("std"); |
| 2 | const testing = std.testing; | 2 | const testing = std.testing; |
| 3 | const expect = testing.expect; | 3 | const expect = testing.expect; |
| 4 | const expectEqual = testing.expectEqual; | 4 | const expectEqual = testing.expectEqual; |
| 5 | const builtin = @import("builtin"); | ||
| 5 | 6 | ||
| 6 | test "self-referential struct through a slice of optional" { | 7 | test "self-referential struct through a slice of optional" { |
| 8 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 7 | const S = struct { | 11 | const S = struct { |
| 8 | const Node = struct { | 12 | const Node = struct { |
| 9 | children: []?Node, | 13 | children: []?Node, |
test/behavior/union.zig+2| ... | @@ -362,6 +362,8 @@ pub const FooUnion = union(enum) { | ... | @@ -362,6 +362,8 @@ pub const FooUnion = union(enum) { |
| 362 | var glbl_array: [2]FooUnion = undefined; | 362 | var glbl_array: [2]FooUnion = undefined; |
| 363 | 363 | ||
| 364 | test "initialize global array of union" { | 364 | test "initialize global array of union" { |
| 365 | if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 366 | |||
| 365 | glbl_array[1] = FooUnion{ .U1 = 2 }; | 367 | glbl_array[1] = FooUnion{ .U1 = 2 }; |
| 366 | glbl_array[0] = FooUnion{ .U0 = 1 }; | 368 | glbl_array[0] = FooUnion{ .U0 = 1 }; |
| 367 | try expect(glbl_array[0].U0 == 1); | 369 | try expect(glbl_array[0].U0 == 1); |