authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-26 21:39:43-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-26 21:39:50-04:00
log7894703ee74a915206143f0b3efea082f999bb86
treef3a5df459e0a043fae677b5d6a178619052ae047
parent69abc945e45af3f447f9ee07d426d1ec40cf3f15

aarch64: implement more optional/error union/union support


13 files changed, 342 insertions(+), 68 deletions(-)

lib/compiler_rt.zig+1-1
...@@ -240,7 +240,7 @@ comptime {...@@ -240,7 +240,7 @@ comptime {
240 _ = @import("compiler_rt/udivmodti4.zig");240 _ = @import("compiler_rt/udivmodti4.zig");
241241
242 // extra242 // extra
243 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");243 _ = @import("compiler_rt/os_version_check.zig");
244 _ = @import("compiler_rt/emutls.zig");244 _ = @import("compiler_rt/emutls.zig");
245 _ = @import("compiler_rt/arm.zig");245 _ = @import("compiler_rt/arm.zig");
246 _ = @import("compiler_rt/aulldiv.zig");246 _ = @import("compiler_rt/aulldiv.zig");
src/codegen/aarch64/Select.zig+341-29
...@@ -584,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -584,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
584584
585 air_body_index += 1;585 air_body_index += 1;
586 },586 },
587 .@"try", .try_cold, .try_ptr, .try_ptr_cold => {587 .@"try", .try_cold => {
588 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;588 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
589 const extra = isel.air.extraData(Air.Try, pl_op.payload);589 const extra = isel.air.extraData(Air.Try, pl_op.payload);
590590
...@@ -596,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -596,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
596 air_inst_index = air_body[air_body_index];596 air_inst_index = air_body[air_body_index];
597 continue :air_tag air_tags[@intFromEnum(air_inst_index)];597 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
598 },598 },
599 .try_ptr, .try_ptr_cold => {
600 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
601 const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
602
603 try isel.analyzeUse(extra.data.ptr);
604 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
605 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
606
607 air_body_index += 1;
608 air_inst_index = air_body[air_body_index];
609 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
610 },
599 .ret, .ret_safe, .ret_load => {611 .ret, .ret_safe, .ret_load => {
600 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;612 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
601 isel.returns = true;613 isel.returns = true;
...@@ -4760,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -4760,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
4760 const error_set_part_vi = try error_set_part_it.only(isel);4772 const error_set_part_vi = try error_set_part_it.only(isel);
4761 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);4773 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
4762 try isel.emit(.cbz(4774 try isel.emit(.cbz(
4763 switch (error_set_part_vi.?.size(isel)) {4775 error_set_part_mat.ra.w(),
4764 else => unreachable,
4765 1...4 => error_set_part_mat.ra.w(),
4766 5...8 => error_set_part_mat.ra.x(),
4767 },
4768 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),4776 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
4769 ));4777 ));
4770 try error_set_part_mat.finish(isel);4778 try error_set_part_mat.finish(isel);
47714779
4772 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4780 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4773 },4781 },
4782 .try_ptr, .try_ptr_cold => {
4783 const ty_pl = air.data(air.inst_index).ty_pl;
4784 const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
4785 const error_union_ty = isel.air.typeOf(extra.data.ptr, ip).childType(zcu);
4786 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
4787 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
4788
4789 const error_union_ptr_vi = try isel.use(extra.data.ptr);
4790 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
4791 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
4792 defer payload_ptr_vi.value.deref(isel);
4793 switch (codegen.errUnionPayloadOffset(ty_pl.ty.toType().childType(zcu), zcu)) {
4794 0 => try payload_ptr_vi.value.move(isel, extra.data.ptr),
4795 else => |payload_offset| {
4796 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
4797 const lo12: u12 = @truncate(payload_offset >> 0);
4798 const hi12: u12 = @intCast(payload_offset >> 12);
4799 if (hi12 > 0) try isel.emit(.add(
4800 payload_ptr_ra.x(),
4801 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
4802 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
4803 ));
4804 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
4805 },
4806 }
4807 }
4808
4809 const cont_label = isel.instructions.items.len;
4810 const cont_live_registers = isel.live_registers;
4811 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
4812 try isel.merge(&cont_live_registers, .{});
4813
4814 const error_set_ra = try isel.allocIntReg();
4815 defer isel.freeReg(error_set_ra);
4816 try isel.loadReg(
4817 error_set_ra,
4818 ZigType.fromInterned(error_union_info.error_set_type).abiSize(zcu),
4819 .unsigned,
4820 error_union_ptr_mat.ra,
4821 codegen.errUnionErrorOffset(payload_ty, zcu),
4822 );
4823 try error_union_ptr_mat.finish(isel);
4824 try isel.emit(.cbz(
4825 error_set_ra.w(),
4826 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
4827 ));
4828
4829 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4830 },
4774 .dbg_stmt => {4831 .dbg_stmt => {
4775 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4832 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4776 },4833 },
...@@ -5403,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -5403,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
5403 }5460 }
5404 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5461 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5405 },5462 },
5406 .optional_payload_ptr => {
5407 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
5408 defer dst_vi.value.deref(isel);
5409 const ty_op = air.data(air.inst_index).ty_op;
5410 try dst_vi.value.move(isel, ty_op.operand);
5411 }
5412 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5413 },
5414 .optional_payload => {5463 .optional_payload => {
5415 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {5464 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
5416 defer payload_vi.value.deref(isel);5465 defer payload_vi.value.deref(isel);
...@@ -5429,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -5429,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
5429 }5478 }
5430 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5479 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5431 },5480 },
5481 .optional_payload_ptr => {
5482 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
5483 defer payload_ptr_vi.value.deref(isel);
5484 const ty_op = air.data(air.inst_index).ty_op;
5485 try payload_ptr_vi.value.move(isel, ty_op.operand);
5486 }
5487 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5488 },
5489 .optional_payload_ptr_set => {
5490 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
5491 defer payload_ptr_vi.value.deref(isel);
5492 const ty_op = air.data(air.inst_index).ty_op;
5493 const opt_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
5494 if (!opt_ty.optionalReprIsPayload(zcu)) {
5495 const opt_ptr_vi = try isel.use(ty_op.operand);
5496 const opt_ptr_mat = try opt_ptr_vi.matReg(isel);
5497 const has_value_ra = try isel.allocIntReg();
5498 defer isel.freeReg(has_value_ra);
5499 try isel.storeReg(
5500 has_value_ra,
5501 1,
5502 opt_ptr_mat.ra,
5503 opt_ty.optionalChild(zcu).abiSize(zcu),
5504 );
5505 try opt_ptr_mat.finish(isel);
5506 try isel.emit(.movz(has_value_ra.w(), 1, .{ .lsl = .@"0" }));
5507 }
5508 try payload_ptr_vi.value.move(isel, ty_op.operand);
5509 }
5510 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5511 },
5432 .wrap_optional => {5512 .wrap_optional => {
5433 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {5513 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
5434 defer opt_vi.value.deref(isel);5514 defer opt_vi.value.deref(isel);
...@@ -5486,6 +5566,93 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -5486,6 +5566,93 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
5486 }5566 }
5487 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5567 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5488 },5568 },
5569 .unwrap_errunion_payload_ptr => {
5570 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
5571 defer payload_ptr_vi.value.deref(isel);
5572 const ty_op = air.data(air.inst_index).ty_op;
5573 switch (codegen.errUnionPayloadOffset(ty_op.ty.toType().childType(zcu), zcu)) {
5574 0 => try payload_ptr_vi.value.move(isel, ty_op.operand),
5575 else => |payload_offset| {
5576 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
5577 const error_union_ptr_vi = try isel.use(ty_op.operand);
5578 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5579 const lo12: u12 = @truncate(payload_offset >> 0);
5580 const hi12: u12 = @intCast(payload_offset >> 12);
5581 if (hi12 > 0) try isel.emit(.add(
5582 payload_ptr_ra.x(),
5583 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5584 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5585 ));
5586 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5587 try error_union_ptr_mat.finish(isel);
5588 },
5589 }
5590 }
5591 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5592 },
5593 .unwrap_errunion_err_ptr => {
5594 if (isel.live_values.fetchRemove(air.inst_index)) |error_ptr_vi| unused: {
5595 defer error_ptr_vi.value.deref(isel);
5596 const ty_op = air.data(air.inst_index).ty_op;
5597 switch (codegen.errUnionErrorOffset(
5598 isel.air.typeOf(ty_op.operand, ip).childType(zcu).errorUnionPayload(zcu),
5599 zcu,
5600 )) {
5601 0 => try error_ptr_vi.value.move(isel, ty_op.operand),
5602 else => |error_offset| {
5603 const error_ptr_ra = try error_ptr_vi.value.defReg(isel) orelse break :unused;
5604 const error_union_ptr_vi = try isel.use(ty_op.operand);
5605 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5606 const lo12: u12 = @truncate(error_offset >> 0);
5607 const hi12: u12 = @intCast(error_offset >> 12);
5608 if (hi12 > 0) try isel.emit(.add(
5609 error_ptr_ra.x(),
5610 if (lo12 > 0) error_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5611 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5612 ));
5613 if (lo12 > 0) try isel.emit(.add(error_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5614 try error_union_ptr_mat.finish(isel);
5615 },
5616 }
5617 }
5618 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5619 },
5620 .errunion_payload_ptr_set => {
5621 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
5622 defer payload_ptr_vi.value.deref(isel);
5623 const ty_op = air.data(air.inst_index).ty_op;
5624 const payload_ty = ty_op.ty.toType().childType(zcu);
5625 const error_union_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
5626 const error_set_size = error_union_ty.errorUnionSet(zcu).abiSize(zcu);
5627 const error_union_ptr_vi = try isel.use(ty_op.operand);
5628 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5629 if (error_set_size > 0) try isel.storeReg(
5630 .zr,
5631 error_set_size,
5632 error_union_ptr_mat.ra,
5633 codegen.errUnionErrorOffset(payload_ty, zcu),
5634 );
5635 switch (codegen.errUnionPayloadOffset(payload_ty, zcu)) {
5636 0 => {
5637 try error_union_ptr_mat.finish(isel);
5638 try payload_ptr_vi.value.move(isel, ty_op.operand);
5639 },
5640 else => |payload_offset| {
5641 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
5642 const lo12: u12 = @truncate(payload_offset >> 0);
5643 const hi12: u12 = @intCast(payload_offset >> 12);
5644 if (hi12 > 0) try isel.emit(.add(
5645 payload_ptr_ra.x(),
5646 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5647 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5648 ));
5649 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5650 try error_union_ptr_mat.finish(isel);
5651 },
5652 }
5653 }
5654 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5655 },
5489 .wrap_errunion_payload => {5656 .wrap_errunion_payload => {
5490 if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {5657 if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {
5491 defer error_union_vi.value.deref(isel);5658 defer error_union_vi.value.deref(isel);
...@@ -5672,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -5672,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
5672 }5839 }
5673 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5840 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5674 },5841 },
5842 .set_union_tag => {
5843 const bin_op = air.data(air.inst_index).bin_op;
5844 const union_ty = isel.air.typeOf(bin_op.lhs, ip).childType(zcu);
5845 const union_layout = union_ty.unionGetLayout(zcu);
5846 const tag_vi = try isel.use(bin_op.rhs);
5847 const union_ptr_vi = try isel.use(bin_op.lhs);
5848 const union_ptr_mat = try union_ptr_vi.matReg(isel);
5849 try tag_vi.store(isel, isel.air.typeOf(bin_op.rhs, ip), union_ptr_mat.ra, .{
5850 .offset = union_layout.tagOffset(),
5851 });
5852 try union_ptr_mat.finish(isel);
5853 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5854 },
5855 .get_union_tag => {
5856 if (isel.live_values.fetchRemove(air.inst_index)) |tag_vi| {
5857 defer tag_vi.value.deref(isel);
5858 const ty_op = air.data(air.inst_index).ty_op;
5859 const union_ty = isel.air.typeOf(ty_op.operand, ip);
5860 const union_layout = union_ty.unionGetLayout(zcu);
5861 const union_vi = try isel.use(ty_op.operand);
5862 var tag_part_it = union_vi.field(union_ty, union_layout.tagOffset(), union_layout.tag_size);
5863 const tag_part_vi = try tag_part_it.only(isel);
5864 try tag_vi.value.copy(isel, ty_op.ty.toType(), tag_part_vi.?);
5865 }
5866 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5867 },
5675 .slice => {5868 .slice => {
5676 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {5869 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
5677 defer slice_vi.value.deref(isel);5870 defer slice_vi.value.deref(isel);
...@@ -6541,8 +6734,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -6541,8 +6734,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
6541 if (ptr_part_ra == null and len_part_ra == null) break :unused;6734 if (ptr_part_ra == null and len_part_ra == null) break :unused;
65426735
6543 const un_op = air.data(air.inst_index).un_op;6736 const un_op = air.data(air.inst_index).un_op;
6544 const err_vi = try isel.use(un_op);6737 const error_vi = try isel.use(un_op);
6545 const err_mat = try err_vi.matReg(isel);6738 const error_mat = try error_vi.matReg(isel);
6546 const ptr_ra = try isel.allocIntReg();6739 const ptr_ra = try isel.allocIntReg();
6547 defer isel.freeReg(ptr_ra);6740 defer isel.freeReg(ptr_ra);
6548 const start_ra, const end_ra = range_ras: {6741 const start_ra, const end_ra = range_ras: {
...@@ -6573,7 +6766,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -6573,7 +6766,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
6573 if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 }));6766 if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 }));
6574 try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() }));6767 try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() }));
6575 try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{6768 try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{
6576 .register = err_mat.ra.w(),6769 .register = error_mat.ra.w(),
6577 .extend = switch (zcu.errorSetBits()) {6770 .extend = switch (zcu.errorSetBits()) {
6578 else => unreachable,6771 else => unreachable,
6579 1...8 => .{ .uxtb = 2 },6772 1...8 => .{ .uxtb = 2 },
...@@ -6591,7 +6784,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -6591,7 +6784,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
6591 .reloc = .{ .label = @intCast(isel.instructions.items.len) },6784 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6592 });6785 });
6593 try isel.emit(.adrp(ptr_ra.x(), 0));6786 try isel.emit(.adrp(ptr_ra.x(), 0));
6594 try err_mat.finish(isel);6787 try error_mat.finish(isel);
6595 }6788 }
6596 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;6789 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6597 },6790 },
...@@ -6893,11 +7086,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -6893,11 +7086,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
6893 try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls)));7086 try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls)));
68947087
6895 const un_op = air.data(air.inst_index).un_op;7088 const un_op = air.data(air.inst_index).un_op;
6896 const err_vi = try isel.use(un_op);7089 const error_vi = try isel.use(un_op);
6897 const err_mat = try err_vi.matReg(isel);7090 const error_mat = try error_vi.matReg(isel);
6898 const ptr_ra = try isel.allocIntReg();7091 const ptr_ra = try isel.allocIntReg();
6899 defer isel.freeReg(ptr_ra);7092 defer isel.freeReg(ptr_ra);
6900 try isel.emit(.subs(.wzr, err_mat.ra.w(), .{ .register = ptr_ra.w() }));7093 try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
6901 try isel.lazy_relocs.append(gpa, .{7094 try isel.lazy_relocs.append(gpa, .{
6902 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },7095 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
6903 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7096 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
...@@ -6908,7 +7101,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -6908,7 +7101,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
6908 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7101 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6909 });7102 });
6910 try isel.emit(.adrp(ptr_ra.x(), 0));7103 try isel.emit(.adrp(ptr_ra.x(), 0));
6911 try err_mat.finish(isel);7104 try error_mat.finish(isel);
6912 }7105 }
6913 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;7106 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6914 },7107 },
...@@ -9529,8 +9722,14 @@ pub const Value = struct {...@@ -9529,8 +9722,14 @@ pub const Value = struct {
9529 } },9722 } },
9530 },9723 },
9531 .struct_type => {9724 .struct_type => {
9532 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9533 const loaded_struct = ip.loadStructType(ty.toIntern());9725 const loaded_struct = ip.loadStructType(ty.toIntern());
9726 switch (loaded_struct.layout) {
9727 .auto, .@"extern" => {},
9728 .@"packed" => continue :type_key .{
9729 .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
9730 },
9731 }
9732 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9534 if (loaded_struct.field_types.len > Value.max_parts and9733 if (loaded_struct.field_types.len > Value.max_parts and
9535 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)9734 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
9536 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});9735 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
...@@ -9638,6 +9837,77 @@ pub const Value = struct {...@@ -9638,6 +9837,77 @@ pub const Value = struct {
9638 if (part.is_vector) subpart_vi.setIsVector(isel);9837 if (part.is_vector) subpart_vi.setIsVector(isel);
9639 }9838 }
9640 },9839 },
9840 .union_type => {
9841 const loaded_union = ip.loadUnionType(ty.toIntern());
9842 switch (loaded_union.flagsUnordered(ip).layout) {
9843 .auto, .@"extern" => {},
9844 .@"packed" => continue :type_key .{ .int_type = .{
9845 .signedness = .unsigned,
9846 .bits = @intCast(ty.bitSize(zcu)),
9847 } },
9848 }
9849 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9850 if ((std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
9851 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
9852 const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
9853 const alignment = vi.alignment(isel);
9854 const tag_offset = union_layout.tagOffset();
9855 const payload_offset = union_layout.payloadOffset();
9856 const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness };
9857 var parts: [2]Part = undefined;
9858 var parts_len: Value.PartsLen = 0;
9859 var field_end: u64 = 0;
9860 for (0..2) |field_index| {
9861 const field: enum { tag, payload } = switch (field_index) {
9862 0 => if (tag_offset < payload_offset) .tag else .payload,
9863 1 => if (tag_offset < payload_offset) .payload else .tag,
9864 else => unreachable,
9865 };
9866 const field_size, const field_begin = switch (field) {
9867 .tag => .{ union_layout.tag_size, tag_offset },
9868 .payload => .{ union_layout.payload_size, payload_offset },
9869 };
9870 if (field_begin >= offset + size) break;
9871 if (field_size == 0) continue;
9872 field_end = field_begin + field_size;
9873 if (field_end <= offset) continue;
9874 const field_signedness = field_signedness: switch (field) {
9875 .tag => {
9876 if (offset >= field_begin and offset + size <= field_begin + field_size) {
9877 ty = .fromInterned(loaded_union.enum_tag_ty);
9878 ty_size = field_size;
9879 offset -= field_begin;
9880 continue :type_key ip.indexToKey(loaded_union.enum_tag_ty);
9881 }
9882 break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness;
9883 },
9884 .payload => null,
9885 };
9886 if (parts_len > 0) combine: {
9887 const prev_part = &parts[parts_len - 1];
9888 const combined_size = field_end - prev_part.offset;
9889 if (combined_size > @as(u64, 1) << @min(
9890 min_part_log2_stride,
9891 alignment.toLog2Units(),
9892 @ctz(prev_part.offset),
9893 )) break :combine;
9894 prev_part.size = combined_size;
9895 prev_part.signedness = null;
9896 continue;
9897 }
9898 parts[parts_len] = .{
9899 .offset = field_begin,
9900 .size = field_size,
9901 .signedness = field_signedness,
9902 };
9903 parts_len += 1;
9904 }
9905 vi.setParts(isel, parts_len);
9906 for (parts[0..parts_len]) |part| {
9907 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
9908 if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
9909 }
9910 },
9641 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },9911 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
9642 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),9912 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
9643 .error_set_type,9913 .error_set_type,
...@@ -10075,7 +10345,11 @@ pub const Value = struct {...@@ -10075,7 +10345,11 @@ pub const Value = struct {
10075 };10345 };
10076 },10346 },
10077 .slice => |slice| switch (offset) {10347 .slice => |slice| switch (offset) {
10078 0 => continue :constant_key .{ .ptr = ip.indexToKey(slice.ptr).ptr },10348 0 => continue :constant_key switch (ip.indexToKey(slice.ptr)) {
10349 else => unreachable,
10350 .undef => |undef| .{ .undef = undef },
10351 .ptr => |ptr| .{ .ptr = ptr },
10352 },
10079 else => {10353 else => {
10080 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));10354 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
10081 offset = 0;10355 offset = 0;
...@@ -11128,16 +11402,14 @@ pub const CallAbiIterator = struct {...@@ -11128,16 +11402,14 @@ pub const CallAbiIterator = struct {
11128 {11402 {
11129 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);11403 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
11130 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);11404 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
11131 const size = error_set_ty.abiSize(zcu);11405 const end = offset % 8 + error_set_ty.abiSize(zcu);
11132 const end = offset % 8 + size;
11133 const part_index: usize = @intCast(offset / 8);11406 const part_index: usize = @intCast(offset / 8);
11134 sizes[part_index] = @max(sizes[part_index], @min(end, 8));11407 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11135 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);11408 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
11136 }11409 }
11137 {11410 {
11138 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);11411 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
11139 const size = payload_ty.abiSize(zcu);11412 const end = offset % 8 + payload_ty.abiSize(zcu);
11140 const end = offset % 8 + size;
11141 const part_index: usize = @intCast(offset / 8);11413 const part_index: usize = @intCast(offset / 8);
11142 sizes[part_index] = @max(sizes[part_index], @min(end, 8));11414 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11143 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);11415 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
...@@ -11181,8 +11453,14 @@ pub const CallAbiIterator = struct {...@@ -11181,8 +11453,14 @@ pub const CallAbiIterator = struct {
11181 => unreachable,11453 => unreachable,
11182 },11454 },
11183 .struct_type => {11455 .struct_type => {
11184 const size = wip_vi.size(isel);
11185 const loaded_struct = ip.loadStructType(ty.toIntern());11456 const loaded_struct = ip.loadStructType(ty.toIntern());
11457 switch (loaded_struct.layout) {
11458 .auto, .@"extern" => {},
11459 .@"packed" => continue :type_key .{
11460 .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
11461 },
11462 }
11463 const size = wip_vi.size(isel);
11186 if (size <= 16 * 4) homogeneous_aggregate: {11464 if (size <= 16 * 4) homogeneous_aggregate: {
11187 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;11465 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
11188 const parts_len = @shrExact(size, fdt.log2Size());11466 const parts_len = @shrExact(size, fdt.log2Size());
...@@ -11267,6 +11545,40 @@ pub const CallAbiIterator = struct {...@@ -11267,6 +11545,40 @@ pub const CallAbiIterator = struct {
11267 else => it.indirect(isel, wip_vi),11545 else => it.indirect(isel, wip_vi),
11268 }11546 }
11269 },11547 },
11548 .union_type => {
11549 const loaded_union = ip.loadUnionType(ty.toIntern());
11550 switch (loaded_union.flagsUnordered(ip).layout) {
11551 .auto, .@"extern" => {},
11552 .@"packed" => continue :type_key .{ .int_type = .{
11553 .signedness = .unsigned,
11554 .bits = @intCast(ty.bitSize(zcu)),
11555 } },
11556 }
11557 switch (wip_vi.size(isel)) {
11558 0 => unreachable,
11559 1...8 => it.integer(isel, wip_vi),
11560 9...16 => {
11561 const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
11562 var sizes: [2]u64 = @splat(0);
11563 {
11564 const offset = union_layout.tagOffset();
11565 const end = offset % 8 + union_layout.tag_size;
11566 const part_index: usize = @intCast(offset / 8);
11567 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11568 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
11569 }
11570 {
11571 const offset = union_layout.payloadOffset();
11572 const end = offset % 8 + union_layout.payload_size;
11573 const part_index: usize = @intCast(offset / 8);
11574 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11575 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
11576 }
11577 it.integers(isel, wip_vi, sizes);
11578 },
11579 else => it.indirect(isel, wip_vi),
11580 }
11581 },
11270 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },11582 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
11271 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),11583 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
11272 .error_set_type,11584 .error_set_type,
test/behavior/decl_literals.zig-2
...@@ -33,7 +33,6 @@ test "decl literal with pointer" {...@@ -33,7 +33,6 @@ test "decl literal with pointer" {
33}33}
3434
35test "call decl literal with optional" {35test "call decl literal with optional" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -74,7 +73,6 @@ test "call decl literal" {...@@ -74,7 +73,6 @@ test "call decl literal" {
74}73}
7574
76test "call decl literal with error union" {75test "call decl literal with error union" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
7977
80 const S = struct {78 const S = struct {
test/behavior/error.zig-1
...@@ -943,7 +943,6 @@ test "optional error set function parameter" {...@@ -943,7 +943,6 @@ test "optional error set function parameter" {
943}943}
944944
945test "returning an error union containing a type with no runtime bits" {945test "returning an error union containing a type with no runtime bits" {
946 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
948 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;947 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
949948
test/behavior/field_parent_ptr.zig-2
...@@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {...@@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
587}587}
588588
589test "@fieldParentPtr unaligned packed struct" {589test "@fieldParentPtr unaligned packed struct" {
590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
591 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;590 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
592 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;591 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
593 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;592 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {...@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {
726}725}
727726
728test "@fieldParentPtr aligned packed struct" {727test "@fieldParentPtr aligned packed struct" {
729 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
731 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;729 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
732 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/inline_switch.zig-1
...@@ -43,7 +43,6 @@ test "inline switch enums" {...@@ -43,7 +43,6 @@ test "inline switch enums" {
4343
44const U = union(E) { a: void, b: u2, c: u3, d: u4 };44const U = union(E) { a: void, b: u2, c: u3, d: u4 };
45test "inline switch unions" {45test "inline switch unions" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4948
test/behavior/optional.zig-2
...@@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {...@@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {
319}319}
320320
321test "coerce an anon struct literal to optional struct" {321test "coerce an anon struct literal to optional struct" {
322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;324 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {...@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {
447}446}
448447
449test "optional pointer to zero bit error union payload" {448test "optional pointer to zero bit error union payload" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/struct.zig-5
...@@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {...@@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {
797}797}
798798
799test "non-packed struct with u128 entry in union" {799test "non-packed struct with u128 entry in union" {
800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;802 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {...@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {
1026}1025}
10271026
1028test "for loop over pointers to struct, getting field from struct pointer" {1027test "for loop over pointers to struct, getting field from struct pointer" {
1029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1030 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1028 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1031 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1030 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {...@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {
1093}1091}
10941092
1095test "anon init through optional" {1093test "anon init through optional" {
1096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1097 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1094 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1098 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1095 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1099 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1096 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1113,7 +1110,6 @@ test "anon init through optional" {...@@ -1113,7 +1110,6 @@ test "anon init through optional" {
1113}1110}
11141111
1115test "anon init through error union" {1112test "anon init through error union" {
1116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1119 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1115 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1398,7 +1394,6 @@ test "struct has only one reference" {...@@ -1398,7 +1394,6 @@ test "struct has only one reference" {
1398}1394}
13991395
1400test "no dependency loop on pointer to optional struct" {1396test "no dependency loop on pointer to optional struct" {
1401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14041399
test/behavior/switch.zig-4
...@@ -299,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {...@@ -299,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
299}299}
300300
301test "switch on enum using pointer capture" {301test "switch on enum using pointer capture" {
302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
305304
...@@ -360,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {...@@ -360,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
360}359}
361360
362test "switch on union with some prongs capturing" {361test "switch on union with some prongs capturing" {
363 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
366364
...@@ -975,8 +973,6 @@ test "switch prong captures range" {...@@ -975,8 +973,6 @@ test "switch prong captures range" {
975}973}
976974
977test "prong with inline call to unreachable" {975test "prong with inline call to unreachable" {
978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
979
980 const U = union(enum) {976 const U = union(enum) {
981 void: void,977 void: void,
982 bool: bool,978 bool: bool,
test/behavior/switch_on_captured_error.zig-1
...@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;...@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8test "switch on error union catch capture" {8test "switch on error union catch capture" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
test/behavior/union.zig-18
...@@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {...@@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {
160}160}
161161
162test "constant tagged union with payload" {162test "constant tagged union with payload" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166165
...@@ -263,7 +262,6 @@ fn testComparison() !void {...@@ -263,7 +262,6 @@ fn testComparison() !void {
263}262}
264263
265test "comparison between union and enum literal" {264test "comparison between union and enum literal" {
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {...@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {
279 C: i32,277 C: i32,
280};278};
281test "cast union to tag type of union" {279test "cast union to tag type of union" {
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285282
...@@ -300,7 +297,6 @@ test "union field access gives the enum values" {...@@ -300,7 +297,6 @@ test "union field access gives the enum values" {
300}297}
301298
302test "cast tag type of union to union" {299test "cast tag type of union to union" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306302
...@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {...@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {
316};312};
317313
318test "implicit cast union to its tag type" {314test "implicit cast union to its tag type" {
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322317
...@@ -495,7 +490,6 @@ test "initialize global array of union" {...@@ -495,7 +490,6 @@ test "initialize global array of union" {
495}490}
496491
497test "update the tag value for zero-sized unions" {492test "update the tag value for zero-sized unions" {
498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501495
...@@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci...@@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci
734}728}
735729
736test "@intFromEnum works on unions" {730test "@intFromEnum works on unions" {
737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
738 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
740733
...@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {...@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {
848}841}
849842
850test "@unionInit can modify a union type" {843test "@unionInit can modify a union type" {
851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
853 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
854846
...@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {...@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {
871}863}
872864
873test "@unionInit can modify a pointer value" {865test "@unionInit can modify a pointer value" {
874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO866 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
877868
...@@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {...@@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {
990}981}
991982
992test "switching on non exhaustive union" {983test "switching on non exhaustive union" {
993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
996986
...@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {...@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {
1176}1166}
11771167
1178test "union tag is set when initiated as a temporary value at runtime" {1168test "union tag is set when initiated as a temporary value at runtime" {
1179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1182 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {...@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {
1216}1205}
12171206
1218test "return an extern union from C calling convention" {1207test "return an extern union from C calling convention" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1210 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {...@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {
1248}1236}
12491237
1250test "noreturn field in union" {1238test "noreturn field in union" {
1251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1239 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12541241
...@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {...@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {
1481}1468}
14821469
1483test "access the tag of a global tagged union" {1470test "access the tag of a global tagged union" {
1484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1485
1486 const U = union(enum) {1471 const U = union(enum) {
1487 a,1472 a,
1488 b: u8,1473 b: u8,
...@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {...@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {
2111}2096}
21122097
2113test "copied union field doesn't alias source" {2098test "copied union field doesn't alias source" {
2114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2101 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2334,8 +2318,6 @@ test "assign global tagged union" {...@@ -2334,8 +2318,6 @@ test "assign global tagged union" {
2334}2318}
23352319
2336test "set mutable union by switching on same union" {2320test "set mutable union by switching on same union" {
2337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2338
2339 const U = union(enum) {2321 const U = union(enum) {
2340 foo,2322 foo,
2341 bar: usize,2323 bar: usize,
test/behavior/union_with_members.zig-1
...@@ -17,7 +17,6 @@ const ET = union(enum) {...@@ -17,7 +17,6 @@ const ET = union(enum) {
17};17};
1818
19test "enum with members" {19test "enum with members" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/while.zig-1
...@@ -344,7 +344,6 @@ test "else continue outer while" {...@@ -344,7 +344,6 @@ test "else continue outer while" {
344}344}
345345
346test "try terminating an infinite loop" {346test "try terminating an infinite loop" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;348 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
350349