mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
aarch64: implement more optional/error union/union support
This commit is contained in:
parent
69abc945e4
commit
7894703ee7
13 changed files with 342 additions and 68 deletions
|
|
@ -240,7 +240,7 @@ comptime {
|
|||
_ = @import("compiler_rt/udivmodti4.zig");
|
||||
|
||||
// extra
|
||||
if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");
|
||||
_ = @import("compiler_rt/os_version_check.zig");
|
||||
_ = @import("compiler_rt/emutls.zig");
|
||||
_ = @import("compiler_rt/arm.zig");
|
||||
_ = @import("compiler_rt/aulldiv.zig");
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
|||
|
||||
air_body_index += 1;
|
||||
},
|
||||
.@"try", .try_cold, .try_ptr, .try_ptr_cold => {
|
||||
.@"try", .try_cold => {
|
||||
const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
|
||||
const extra = isel.air.extraData(Air.Try, pl_op.payload);
|
||||
|
||||
|
|
@ -596,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
|||
air_inst_index = air_body[air_body_index];
|
||||
continue :air_tag air_tags[@intFromEnum(air_inst_index)];
|
||||
},
|
||||
.try_ptr, .try_ptr_cold => {
|
||||
const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
|
||||
const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
|
||||
|
||||
try isel.analyzeUse(extra.data.ptr);
|
||||
try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
|
||||
try isel.def_order.putNoClobber(gpa, air_inst_index, {});
|
||||
|
||||
air_body_index += 1;
|
||||
air_inst_index = air_body[air_body_index];
|
||||
continue :air_tag air_tags[@intFromEnum(air_inst_index)];
|
||||
},
|
||||
.ret, .ret_safe, .ret_load => {
|
||||
const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
|
||||
isel.returns = true;
|
||||
|
|
@ -4760,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
const error_set_part_vi = try error_set_part_it.only(isel);
|
||||
const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
|
||||
try isel.emit(.cbz(
|
||||
switch (error_set_part_vi.?.size(isel)) {
|
||||
else => unreachable,
|
||||
1...4 => error_set_part_mat.ra.w(),
|
||||
5...8 => error_set_part_mat.ra.x(),
|
||||
},
|
||||
error_set_part_mat.ra.w(),
|
||||
@intCast((isel.instructions.items.len + 1 - cont_label) << 2),
|
||||
));
|
||||
try error_set_part_mat.finish(isel);
|
||||
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.try_ptr, .try_ptr_cold => {
|
||||
const ty_pl = air.data(air.inst_index).ty_pl;
|
||||
const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
|
||||
const error_union_ty = isel.air.typeOf(extra.data.ptr, ip).childType(zcu);
|
||||
const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
|
||||
const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
|
||||
|
||||
const error_union_ptr_vi = try isel.use(extra.data.ptr);
|
||||
const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
|
||||
defer payload_ptr_vi.value.deref(isel);
|
||||
switch (codegen.errUnionPayloadOffset(ty_pl.ty.toType().childType(zcu), zcu)) {
|
||||
0 => try payload_ptr_vi.value.move(isel, extra.data.ptr),
|
||||
else => |payload_offset| {
|
||||
const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
|
||||
const lo12: u12 = @truncate(payload_offset >> 0);
|
||||
const hi12: u12 = @intCast(payload_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.add(
|
||||
payload_ptr_ra.x(),
|
||||
if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const cont_label = isel.instructions.items.len;
|
||||
const cont_live_registers = isel.live_registers;
|
||||
try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
|
||||
try isel.merge(&cont_live_registers, .{});
|
||||
|
||||
const error_set_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(error_set_ra);
|
||||
try isel.loadReg(
|
||||
error_set_ra,
|
||||
ZigType.fromInterned(error_union_info.error_set_type).abiSize(zcu),
|
||||
.unsigned,
|
||||
error_union_ptr_mat.ra,
|
||||
codegen.errUnionErrorOffset(payload_ty, zcu),
|
||||
);
|
||||
try error_union_ptr_mat.finish(isel);
|
||||
try isel.emit(.cbz(
|
||||
error_set_ra.w(),
|
||||
@intCast((isel.instructions.items.len + 1 - cont_label) << 2),
|
||||
));
|
||||
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.dbg_stmt => {
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
|
|
@ -5403,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.optional_payload_ptr => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
|
||||
defer dst_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
try dst_vi.value.move(isel, ty_op.operand);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.optional_payload => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
|
||||
defer payload_vi.value.deref(isel);
|
||||
|
|
@ -5429,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.optional_payload_ptr => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
|
||||
defer payload_ptr_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
try payload_ptr_vi.value.move(isel, ty_op.operand);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.optional_payload_ptr_set => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
|
||||
defer payload_ptr_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
const opt_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
|
||||
if (!opt_ty.optionalReprIsPayload(zcu)) {
|
||||
const opt_ptr_vi = try isel.use(ty_op.operand);
|
||||
const opt_ptr_mat = try opt_ptr_vi.matReg(isel);
|
||||
const has_value_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(has_value_ra);
|
||||
try isel.storeReg(
|
||||
has_value_ra,
|
||||
1,
|
||||
opt_ptr_mat.ra,
|
||||
opt_ty.optionalChild(zcu).abiSize(zcu),
|
||||
);
|
||||
try opt_ptr_mat.finish(isel);
|
||||
try isel.emit(.movz(has_value_ra.w(), 1, .{ .lsl = .@"0" }));
|
||||
}
|
||||
try payload_ptr_vi.value.move(isel, ty_op.operand);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.wrap_optional => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
|
||||
defer opt_vi.value.deref(isel);
|
||||
|
|
@ -5486,6 +5566,93 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.unwrap_errunion_payload_ptr => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
|
||||
defer payload_ptr_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
switch (codegen.errUnionPayloadOffset(ty_op.ty.toType().childType(zcu), zcu)) {
|
||||
0 => try payload_ptr_vi.value.move(isel, ty_op.operand),
|
||||
else => |payload_offset| {
|
||||
const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
|
||||
const error_union_ptr_vi = try isel.use(ty_op.operand);
|
||||
const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
|
||||
const lo12: u12 = @truncate(payload_offset >> 0);
|
||||
const hi12: u12 = @intCast(payload_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.add(
|
||||
payload_ptr_ra.x(),
|
||||
if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
|
||||
try error_union_ptr_mat.finish(isel);
|
||||
},
|
||||
}
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.unwrap_errunion_err_ptr => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |error_ptr_vi| unused: {
|
||||
defer error_ptr_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
switch (codegen.errUnionErrorOffset(
|
||||
isel.air.typeOf(ty_op.operand, ip).childType(zcu).errorUnionPayload(zcu),
|
||||
zcu,
|
||||
)) {
|
||||
0 => try error_ptr_vi.value.move(isel, ty_op.operand),
|
||||
else => |error_offset| {
|
||||
const error_ptr_ra = try error_ptr_vi.value.defReg(isel) orelse break :unused;
|
||||
const error_union_ptr_vi = try isel.use(ty_op.operand);
|
||||
const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
|
||||
const lo12: u12 = @truncate(error_offset >> 0);
|
||||
const hi12: u12 = @intCast(error_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.add(
|
||||
error_ptr_ra.x(),
|
||||
if (lo12 > 0) error_ptr_ra.x() else error_union_ptr_mat.ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0) try isel.emit(.add(error_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
|
||||
try error_union_ptr_mat.finish(isel);
|
||||
},
|
||||
}
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.errunion_payload_ptr_set => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
|
||||
defer payload_ptr_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
const payload_ty = ty_op.ty.toType().childType(zcu);
|
||||
const error_union_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
|
||||
const error_set_size = error_union_ty.errorUnionSet(zcu).abiSize(zcu);
|
||||
const error_union_ptr_vi = try isel.use(ty_op.operand);
|
||||
const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
|
||||
if (error_set_size > 0) try isel.storeReg(
|
||||
.zr,
|
||||
error_set_size,
|
||||
error_union_ptr_mat.ra,
|
||||
codegen.errUnionErrorOffset(payload_ty, zcu),
|
||||
);
|
||||
switch (codegen.errUnionPayloadOffset(payload_ty, zcu)) {
|
||||
0 => {
|
||||
try error_union_ptr_mat.finish(isel);
|
||||
try payload_ptr_vi.value.move(isel, ty_op.operand);
|
||||
},
|
||||
else => |payload_offset| {
|
||||
const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
|
||||
const lo12: u12 = @truncate(payload_offset >> 0);
|
||||
const hi12: u12 = @intCast(payload_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.add(
|
||||
payload_ptr_ra.x(),
|
||||
if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
|
||||
try error_union_ptr_mat.finish(isel);
|
||||
},
|
||||
}
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.wrap_errunion_payload => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {
|
||||
defer error_union_vi.value.deref(isel);
|
||||
|
|
@ -5672,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.set_union_tag => {
|
||||
const bin_op = air.data(air.inst_index).bin_op;
|
||||
const union_ty = isel.air.typeOf(bin_op.lhs, ip).childType(zcu);
|
||||
const union_layout = union_ty.unionGetLayout(zcu);
|
||||
const tag_vi = try isel.use(bin_op.rhs);
|
||||
const union_ptr_vi = try isel.use(bin_op.lhs);
|
||||
const union_ptr_mat = try union_ptr_vi.matReg(isel);
|
||||
try tag_vi.store(isel, isel.air.typeOf(bin_op.rhs, ip), union_ptr_mat.ra, .{
|
||||
.offset = union_layout.tagOffset(),
|
||||
});
|
||||
try union_ptr_mat.finish(isel);
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.get_union_tag => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |tag_vi| {
|
||||
defer tag_vi.value.deref(isel);
|
||||
const ty_op = air.data(air.inst_index).ty_op;
|
||||
const union_ty = isel.air.typeOf(ty_op.operand, ip);
|
||||
const union_layout = union_ty.unionGetLayout(zcu);
|
||||
const union_vi = try isel.use(ty_op.operand);
|
||||
var tag_part_it = union_vi.field(union_ty, union_layout.tagOffset(), union_layout.tag_size);
|
||||
const tag_part_vi = try tag_part_it.only(isel);
|
||||
try tag_vi.value.copy(isel, ty_op.ty.toType(), tag_part_vi.?);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
.slice => {
|
||||
if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
|
||||
defer slice_vi.value.deref(isel);
|
||||
|
|
@ -6541,8 +6734,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
if (ptr_part_ra == null and len_part_ra == null) break :unused;
|
||||
|
||||
const un_op = air.data(air.inst_index).un_op;
|
||||
const err_vi = try isel.use(un_op);
|
||||
const err_mat = try err_vi.matReg(isel);
|
||||
const error_vi = try isel.use(un_op);
|
||||
const error_mat = try error_vi.matReg(isel);
|
||||
const ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(ptr_ra);
|
||||
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,
|
|||
if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 }));
|
||||
try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() }));
|
||||
try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{
|
||||
.register = err_mat.ra.w(),
|
||||
.register = error_mat.ra.w(),
|
||||
.extend = switch (zcu.errorSetBits()) {
|
||||
else => unreachable,
|
||||
1...8 => .{ .uxtb = 2 },
|
||||
|
|
@ -6591,7 +6784,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.adrp(ptr_ra.x(), 0));
|
||||
try err_mat.finish(isel);
|
||||
try error_mat.finish(isel);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
|
|
@ -6893,11 +7086,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls)));
|
||||
|
||||
const un_op = air.data(air.inst_index).un_op;
|
||||
const err_vi = try isel.use(un_op);
|
||||
const err_mat = try err_vi.matReg(isel);
|
||||
const error_vi = try isel.use(un_op);
|
||||
const error_mat = try error_vi.matReg(isel);
|
||||
const ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(ptr_ra);
|
||||
try isel.emit(.subs(.wzr, err_mat.ra.w(), .{ .register = ptr_ra.w() }));
|
||||
try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
|
||||
try isel.lazy_relocs.append(gpa, .{
|
||||
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
|
||||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
|
|
@ -6908,7 +7101,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
|
|||
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
|
||||
});
|
||||
try isel.emit(.adrp(ptr_ra.x(), 0));
|
||||
try err_mat.finish(isel);
|
||||
try error_mat.finish(isel);
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
},
|
||||
|
|
@ -9529,8 +9722,14 @@ pub const Value = struct {
|
|||
} },
|
||||
},
|
||||
.struct_type => {
|
||||
const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
|
||||
const loaded_struct = ip.loadStructType(ty.toIntern());
|
||||
switch (loaded_struct.layout) {
|
||||
.auto, .@"extern" => {},
|
||||
.@"packed" => continue :type_key .{
|
||||
.int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
|
||||
},
|
||||
}
|
||||
const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
|
||||
if (loaded_struct.field_types.len > Value.max_parts and
|
||||
(std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
|
||||
return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
|
||||
|
|
@ -9638,6 +9837,77 @@ pub const Value = struct {
|
|||
if (part.is_vector) subpart_vi.setIsVector(isel);
|
||||
}
|
||||
},
|
||||
.union_type => {
|
||||
const loaded_union = ip.loadUnionType(ty.toIntern());
|
||||
switch (loaded_union.flagsUnordered(ip).layout) {
|
||||
.auto, .@"extern" => {},
|
||||
.@"packed" => continue :type_key .{ .int_type = .{
|
||||
.signedness = .unsigned,
|
||||
.bits = @intCast(ty.bitSize(zcu)),
|
||||
} },
|
||||
}
|
||||
const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
|
||||
if ((std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
|
||||
return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
|
||||
const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
|
||||
const alignment = vi.alignment(isel);
|
||||
const tag_offset = union_layout.tagOffset();
|
||||
const payload_offset = union_layout.payloadOffset();
|
||||
const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness };
|
||||
var parts: [2]Part = undefined;
|
||||
var parts_len: Value.PartsLen = 0;
|
||||
var field_end: u64 = 0;
|
||||
for (0..2) |field_index| {
|
||||
const field: enum { tag, payload } = switch (field_index) {
|
||||
0 => if (tag_offset < payload_offset) .tag else .payload,
|
||||
1 => if (tag_offset < payload_offset) .payload else .tag,
|
||||
else => unreachable,
|
||||
};
|
||||
const field_size, const field_begin = switch (field) {
|
||||
.tag => .{ union_layout.tag_size, tag_offset },
|
||||
.payload => .{ union_layout.payload_size, payload_offset },
|
||||
};
|
||||
if (field_begin >= offset + size) break;
|
||||
if (field_size == 0) continue;
|
||||
field_end = field_begin + field_size;
|
||||
if (field_end <= offset) continue;
|
||||
const field_signedness = field_signedness: switch (field) {
|
||||
.tag => {
|
||||
if (offset >= field_begin and offset + size <= field_begin + field_size) {
|
||||
ty = .fromInterned(loaded_union.enum_tag_ty);
|
||||
ty_size = field_size;
|
||||
offset -= field_begin;
|
||||
continue :type_key ip.indexToKey(loaded_union.enum_tag_ty);
|
||||
}
|
||||
break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness;
|
||||
},
|
||||
.payload => null,
|
||||
};
|
||||
if (parts_len > 0) combine: {
|
||||
const prev_part = &parts[parts_len - 1];
|
||||
const combined_size = field_end - prev_part.offset;
|
||||
if (combined_size > @as(u64, 1) << @min(
|
||||
min_part_log2_stride,
|
||||
alignment.toLog2Units(),
|
||||
@ctz(prev_part.offset),
|
||||
)) break :combine;
|
||||
prev_part.size = combined_size;
|
||||
prev_part.signedness = null;
|
||||
continue;
|
||||
}
|
||||
parts[parts_len] = .{
|
||||
.offset = field_begin,
|
||||
.size = field_size,
|
||||
.signedness = field_signedness,
|
||||
};
|
||||
parts_len += 1;
|
||||
}
|
||||
vi.setParts(isel, parts_len);
|
||||
for (parts[0..parts_len]) |part| {
|
||||
const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
|
||||
if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
|
||||
}
|
||||
},
|
||||
.opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
|
||||
.enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
|
||||
.error_set_type,
|
||||
|
|
@ -10075,7 +10345,11 @@ pub const Value = struct {
|
|||
};
|
||||
},
|
||||
.slice => |slice| switch (offset) {
|
||||
0 => continue :constant_key .{ .ptr = ip.indexToKey(slice.ptr).ptr },
|
||||
0 => continue :constant_key switch (ip.indexToKey(slice.ptr)) {
|
||||
else => unreachable,
|
||||
.undef => |undef| .{ .undef = undef },
|
||||
.ptr => |ptr| .{ .ptr = ptr },
|
||||
},
|
||||
else => {
|
||||
assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
|
||||
offset = 0;
|
||||
|
|
@ -11128,16 +11402,14 @@ pub const CallAbiIterator = struct {
|
|||
{
|
||||
const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
|
||||
const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
|
||||
const size = error_set_ty.abiSize(zcu);
|
||||
const end = offset % 8 + size;
|
||||
const end = offset % 8 + error_set_ty.abiSize(zcu);
|
||||
const part_index: usize = @intCast(offset / 8);
|
||||
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
|
||||
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
|
||||
}
|
||||
{
|
||||
const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
|
||||
const size = payload_ty.abiSize(zcu);
|
||||
const end = offset % 8 + size;
|
||||
const end = offset % 8 + payload_ty.abiSize(zcu);
|
||||
const part_index: usize = @intCast(offset / 8);
|
||||
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
|
||||
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
|
||||
|
|
@ -11181,8 +11453,14 @@ pub const CallAbiIterator = struct {
|
|||
=> unreachable,
|
||||
},
|
||||
.struct_type => {
|
||||
const size = wip_vi.size(isel);
|
||||
const loaded_struct = ip.loadStructType(ty.toIntern());
|
||||
switch (loaded_struct.layout) {
|
||||
.auto, .@"extern" => {},
|
||||
.@"packed" => continue :type_key .{
|
||||
.int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
|
||||
},
|
||||
}
|
||||
const size = wip_vi.size(isel);
|
||||
if (size <= 16 * 4) homogeneous_aggregate: {
|
||||
const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
|
||||
const parts_len = @shrExact(size, fdt.log2Size());
|
||||
|
|
@ -11267,6 +11545,40 @@ pub const CallAbiIterator = struct {
|
|||
else => it.indirect(isel, wip_vi),
|
||||
}
|
||||
},
|
||||
.union_type => {
|
||||
const loaded_union = ip.loadUnionType(ty.toIntern());
|
||||
switch (loaded_union.flagsUnordered(ip).layout) {
|
||||
.auto, .@"extern" => {},
|
||||
.@"packed" => continue :type_key .{ .int_type = .{
|
||||
.signedness = .unsigned,
|
||||
.bits = @intCast(ty.bitSize(zcu)),
|
||||
} },
|
||||
}
|
||||
switch (wip_vi.size(isel)) {
|
||||
0 => unreachable,
|
||||
1...8 => it.integer(isel, wip_vi),
|
||||
9...16 => {
|
||||
const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
|
||||
var sizes: [2]u64 = @splat(0);
|
||||
{
|
||||
const offset = union_layout.tagOffset();
|
||||
const end = offset % 8 + union_layout.tag_size;
|
||||
const part_index: usize = @intCast(offset / 8);
|
||||
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
|
||||
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
|
||||
}
|
||||
{
|
||||
const offset = union_layout.payloadOffset();
|
||||
const end = offset % 8 + union_layout.payload_size;
|
||||
const part_index: usize = @intCast(offset / 8);
|
||||
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
|
||||
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
|
||||
}
|
||||
it.integers(isel, wip_vi, sizes);
|
||||
},
|
||||
else => it.indirect(isel, wip_vi),
|
||||
}
|
||||
},
|
||||
.opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
|
||||
.enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
|
||||
.error_set_type,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ test "decl literal with pointer" {
|
|||
}
|
||||
|
||||
test "call decl literal with optional" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -74,7 +73,6 @@ test "call decl literal" {
|
|||
}
|
||||
|
||||
test "call decl literal with error union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
|
|
|
|||
|
|
@ -943,7 +943,6 @@ test "optional error set function parameter" {
|
|||
}
|
||||
|
||||
test "returning an error union containing a type with no runtime bits" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
|
|
|
|||
|
|
@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
|
|||
}
|
||||
|
||||
test "@fieldParentPtr unaligned packed struct" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {
|
|||
}
|
||||
|
||||
test "@fieldParentPtr aligned packed struct" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ test "inline switch enums" {
|
|||
|
||||
const U = union(E) { a: void, b: u2, c: u3, d: u4 };
|
||||
test "inline switch unions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
|
|||
|
|
@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {
|
|||
}
|
||||
|
||||
test "coerce an anon struct literal to optional struct" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {
|
|||
}
|
||||
|
||||
test "optional pointer to zero bit error union payload" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
|
|||
|
|
@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {
|
|||
}
|
||||
|
||||
test "non-packed struct with u128 entry in union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {
|
|||
}
|
||||
|
||||
test "for loop over pointers to struct, getting field from struct pointer" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
|
@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {
|
|||
}
|
||||
|
||||
test "anon init through optional" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -1113,7 +1110,6 @@ test "anon init through optional" {
|
|||
}
|
||||
|
||||
test "anon init through error union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -1398,7 +1394,6 @@ test "struct has only one reference" {
|
|||
}
|
||||
|
||||
test "no dependency loop on pointer to optional struct" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
|
|
|
|||
|
|
@ -299,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
|
|||
}
|
||||
|
||||
test "switch on enum using pointer capture" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -360,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
|
|||
}
|
||||
|
||||
test "switch on union with some prongs capturing" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -975,8 +973,6 @@ test "switch prong captures range" {
|
|||
}
|
||||
|
||||
test "prong with inline call to unreachable" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
const U = union(enum) {
|
||||
void: void,
|
||||
bool: bool,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
|
|||
const builtin = @import("builtin");
|
||||
|
||||
test "switch on error union catch capture" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {
|
|||
}
|
||||
|
||||
test "constant tagged union with payload" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -263,7 +262,6 @@ fn testComparison() !void {
|
|||
}
|
||||
|
||||
test "comparison between union and enum literal" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {
|
|||
C: i32,
|
||||
};
|
||||
test "cast union to tag type of union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -300,7 +297,6 @@ test "union field access gives the enum values" {
|
|||
}
|
||||
|
||||
test "cast tag type of union to union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -316,7 +312,6 @@ const Value2 = union(Letter2) {
|
|||
};
|
||||
|
||||
test "implicit cast union to its tag type" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -495,7 +490,6 @@ test "initialize global array of union" {
|
|||
}
|
||||
|
||||
test "update the tag value for zero-sized unions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci
|
|||
}
|
||||
|
||||
test "@intFromEnum works on unions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -848,7 +841,6 @@ test "@unionInit stored to a const" {
|
|||
}
|
||||
|
||||
test "@unionInit can modify a union type" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {
|
|||
}
|
||||
|
||||
test "@unionInit can modify a pointer value" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {
|
|||
}
|
||||
|
||||
test "switching on non exhaustive union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {
|
|||
}
|
||||
|
||||
test "union tag is set when initiated as a temporary value at runtime" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
|
@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {
|
|||
}
|
||||
|
||||
test "return an extern union from C calling convention" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
|
@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {
|
|||
}
|
||||
|
||||
test "noreturn field in union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
|
@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {
|
|||
}
|
||||
|
||||
test "access the tag of a global tagged union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
const U = union(enum) {
|
||||
a,
|
||||
b: u8,
|
||||
|
|
@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {
|
|||
}
|
||||
|
||||
test "copied union field doesn't alias source" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
@ -2334,8 +2318,6 @@ test "assign global tagged union" {
|
|||
}
|
||||
|
||||
test "set mutable union by switching on same union" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
const U = union(enum) {
|
||||
foo,
|
||||
bar: usize,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ const ET = union(enum) {
|
|||
};
|
||||
|
||||
test "enum with members" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ test "else continue outer while" {
|
|||
}
|
||||
|
||||
test "try terminating an infinite loop" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue