authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-11 19:06:46+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-12 00:01:05+01:00
log2262640e8bf4cbcc4e6a46405d7a5a20562b8e47
tree20d751d8326a7e22665d1edecb4cd7fd680ec84e
parenta5a7f0ff0069d68ad60391dadce52321dd316138

stage2 ARM: lower const slices

Follow-up to e1a535360fb9ed08fc48018571b9702ab12a5876 for ARM This also fixes some stack offset calculation bugs

3 files changed, 119 insertions(+), 108 deletions(-)

src/arch/arm/CodeGen.zig+119-88
...@@ -1170,10 +1170,10 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1170,10 +1170,10 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1170 .dead, .unreach => unreachable,1170 .dead, .unreach => unreachable,
1171 .register => unreachable, // a slice doesn't fit in one register1171 .register => unreachable, // a slice doesn't fit in one register
1172 .stack_argument_offset => |off| {1172 .stack_argument_offset => |off| {
1173 break :result MCValue{ .stack_argument_offset = off };1173 break :result MCValue{ .stack_argument_offset = off + 4 };
1174 },1174 },
1175 .stack_offset => |off| {1175 .stack_offset => |off| {
1176 break :result MCValue{ .stack_offset = off };1176 break :result MCValue{ .stack_offset = off + 4 };
1177 },1177 },
1178 .memory => |addr| {1178 .memory => |addr| {
1179 break :result MCValue{ .memory = addr };1179 break :result MCValue{ .memory = addr };
...@@ -1192,10 +1192,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1192,10 +1192,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1192 .dead, .unreach => unreachable,1192 .dead, .unreach => unreachable,
1193 .register => unreachable, // a slice doesn't fit in one register1193 .register => unreachable, // a slice doesn't fit in one register
1194 .stack_argument_offset => |off| {1194 .stack_argument_offset => |off| {
1195 break :result MCValue{ .stack_argument_offset = off + 4 };1195 break :result MCValue{ .stack_argument_offset = off };
1196 },1196 },
1197 .stack_offset => |off| {1197 .stack_offset => |off| {
1198 break :result MCValue{ .stack_offset = off + 4 };1198 break :result MCValue{ .stack_offset = off };
1199 },1199 },
1200 .memory => |addr| {1200 .memory => |addr| {
1201 break :result MCValue{ .memory = addr + 4 };1201 break :result MCValue{ .memory = addr + 4 };
...@@ -1260,7 +1260,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1260,7 +1260,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1260 defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register});1260 defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register});
12611261
1262 const base_mcv: MCValue = switch (slice_mcv) {1262 const base_mcv: MCValue = switch (slice_mcv) {
1263 .stack_offset => .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, slice_mcv) },1263 .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off + 4 }) },
1264 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),1264 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),
1265 };1265 };
1266 self.register_manager.freezeRegs(&.{base_mcv.register});1266 self.register_manager.freezeRegs(&.{base_mcv.register});
...@@ -1471,36 +1471,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1471,36 +1471,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
14711471
1472 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);1472 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1473 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });1473 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1474 } else if (elem_size == 8) {
1475 // TODO generalize this: maybe add a
1476 // genArmMemcpy function which manually copies
1477 // data if the size is below a certain
1478 // threshold and calls "memcpy" if the size is
1479 // larger
1480
1481 const usize_ty = Type.initTag(.usize);
1482 const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null });
1483 self.register_manager.freezeRegs(&tmp_regs);
1484 defer self.register_manager.unfreezeRegs(&tmp_regs);
1485
1486 _ = try self.addInst(.{
1487 .tag = .ldr,
1488 .data = .{ .rr_offset = .{
1489 .rt = tmp_regs[0],
1490 .rn = reg,
1491 .offset = .{ .offset = Instruction.Offset.none },
1492 } },
1493 });
1494 _ = try self.addInst(.{
1495 .tag = .ldr,
1496 .data = .{ .rr_offset = .{
1497 .rt = tmp_regs[1],
1498 .rn = reg,
1499 .offset = .{ .offset = Instruction.Offset.imm(4) },
1500 } },
1501 });
1502 try self.genSetStack(usize_ty, off, MCValue{ .register = tmp_regs[0] });
1503 try self.genSetStack(usize_ty, off + 4, MCValue{ .register = tmp_regs[1] });
1504 } else {1474 } else {
1505 // TODO optimize the register allocation1475 // TODO optimize the register allocation
1506 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });1476 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
...@@ -1677,7 +1647,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -1677,7 +1647,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
1677 .ptr_stack_offset => |off| {1647 .ptr_stack_offset => |off| {
1678 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };1648 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1679 },1649 },
1680 .stack_argument_offset => {1650 else => {
1681 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{1651 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
1682 .immediate = struct_field_offset,1652 .immediate = struct_field_offset,
1683 });1653 });
...@@ -1699,7 +1669,6 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -1699,7 +1669,6 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
1699 );1669 );
1700 break :result MCValue{ .register = dst_reg };1670 break :result MCValue{ .register = dst_reg };
1701 },1671 },
1702 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
1703 }1672 }
1704 };1673 };
1705}1674}
...@@ -3200,9 +3169,9 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -3200,9 +3169,9 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
3200}3169}
32013170
3202fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {3171fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
3172 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3203 switch (mcv) {3173 switch (mcv) {
3204 .dead => unreachable,3174 .dead => unreachable,
3205 .ptr_embedded_in_code => unreachable,
3206 .unreach, .none => return, // Nothing to do.3175 .unreach, .none => return, // Nothing to do.
3207 .undef => {3176 .undef => {
3208 if (!self.wantSafety())3177 if (!self.wantSafety())
...@@ -3215,23 +3184,16 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3215,23 +3184,16 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3215 else => return self.fail("TODO implement memset", .{}),3184 else => return self.fail("TODO implement memset", .{}),
3216 }3185 }
3217 },3186 },
3218 .ptr_stack_offset => {
3219 const reg = try self.copyToTmpRegister(ty, mcv);
3220 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3221 },
3222 .compare_flags_unsigned,3187 .compare_flags_unsigned,
3223 .compare_flags_signed,3188 .compare_flags_signed,
3224 .immediate,3189 .immediate,
3190 .ptr_stack_offset,
3191 .ptr_embedded_in_code,
3225 => {3192 => {
3226 const reg = try self.copyToTmpRegister(ty, mcv);3193 const reg = try self.copyToTmpRegister(ty, mcv);
3227 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3194 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3228 },3195 },
3229 .embedded_in_code => |code_offset| {
3230 _ = code_offset;
3231 return self.fail("TODO implement set stack variable from embedded_in_code", .{});
3232 },
3233 .register => |reg| {3196 .register => |reg| {
3234 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3235 const adj_off = stack_offset + abi_size;3197 const adj_off = stack_offset + abi_size;
32363198
3237 switch (abi_size) {3199 switch (abi_size) {
...@@ -3279,24 +3241,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3279,24 +3241,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3279 }3241 }
3280 },3242 },
3281 .memory,3243 .memory,
3244 .embedded_in_code,
3282 .stack_argument_offset,3245 .stack_argument_offset,
3246 .stack_offset,
3283 => {3247 => {
3284 if (ty.abiSize(self.target.*) <= 4) {3248 switch (mcv) {
3285 const reg = try self.copyToTmpRegister(ty, mcv);3249 .stack_offset => |off| {
3286 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3250 if (stack_offset == off)
3287 } else {3251 return; // Copy stack variable to itself; nothing to do.
3288 return self.fail("TODO implement memcpy", .{});3252 },
3253 else => {},
3289 }3254 }
3290 },
3291 .stack_offset => |off| {
3292 if (stack_offset == off)
3293 return; // Copy stack variable to itself; nothing to do.
32943255
3295 if (ty.abiSize(self.target.*) <= 4) {3256 if (abi_size <= 4) {
3296 const reg = try self.copyToTmpRegister(ty, mcv);3257 const reg = try self.copyToTmpRegister(ty, mcv);
3297 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3258 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3298 } else {3259 } else {
3299 // TODO optimize the register allocation3260 // TODO call extern memcpy
3300 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });3261 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
3301 const src_reg = regs[0];3262 const src_reg = regs[0];
3302 const dst_reg = regs[1];3263 const dst_reg = regs[1];
...@@ -3304,22 +3265,31 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3304,22 +3265,31 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3304 const count_reg = regs[3];3265 const count_reg = regs[3];
3305 const tmp_reg = regs[4];3266 const tmp_reg = regs[4];
33063267
3307 // sub src_reg, fp, #off3268 switch (mcv) {
3308 const adj_src_offset = off + @intCast(u32, ty.abiSize(self.target.*));3269 .stack_offset => |off| {
3309 const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else {3270 // sub src_reg, fp, #off
3310 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});3271 const adj_src_offset = off + @intCast(u32, abi_size);
3311 };3272 const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else {
3312 _ = try self.addInst(.{3273 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3313 .tag = .sub,3274 };
3314 .data = .{ .rr_op = .{3275 _ = try self.addInst(.{
3315 .rd = src_reg,3276 .tag = .sub,
3316 .rn = .fp,3277 .data = .{ .rr_op = .{
3317 .op = src_offset_op,3278 .rd = src_reg,
3318 } },3279 .rn = .fp,
3319 });3280 .op = src_offset_op,
3281 } },
3282 });
3283 },
3284 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
3285 .embedded_in_code,
3286 .stack_argument_offset,
3287 => return self.fail("TODO genSetStack with src={}", .{mcv}),
3288 else => unreachable,
3289 }
33203290
3321 // sub dst_reg, fp, #stack_offset3291 // sub dst_reg, fp, #stack_offset
3322 const adj_dst_offset = stack_offset + @intCast(u32, ty.abiSize(self.target.*));3292 const adj_dst_offset = stack_offset + abi_size;
3323 const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else {3293 const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else {
3324 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});3294 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3325 };3295 };
...@@ -3332,9 +3302,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3332,9 +3302,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3332 } },3302 } },
3333 });3303 });
33343304
3335 // mov len, #elem_size3305 // mov len, #abi_size
3336 const elem_size = @intCast(u32, ty.abiSize(self.target.*));3306 const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(abi_size)) |x| x else {
3337 const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(elem_size)) |x| x else {
3338 return self.fail("TODO load: set reg to elem_size with all possible sizes", .{});3307 return self.fail("TODO load: set reg to elem_size with all possible sizes", .{});
3339 };3308 };
3340 _ = try self.addInst(.{3309 _ = try self.addInst(.{
...@@ -3619,6 +3588,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3619,6 +3588,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3619}3588}
36203589
3621fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {3590fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
3591 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3622 switch (mcv) {3592 switch (mcv) {
3623 .dead => unreachable,3593 .dead => unreachable,
3624 .none, .unreach => return,3594 .none, .unreach => return,
...@@ -3634,7 +3604,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -3634,7 +3604,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
3634 }3604 }
3635 },3605 },
3636 .register => |reg| {3606 .register => |reg| {
3637 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3638 const adj_off = stack_offset - abi_size;3607 const adj_off = stack_offset - abi_size;
36393608
3640 switch (abi_size) {3609 switch (abi_size) {
...@@ -3675,28 +3644,86 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -3675,28 +3644,86 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
3675 else => return self.fail("TODO implement storing other types abi_size={}", .{abi_size}),3644 else => return self.fail("TODO implement storing other types abi_size={}", .{abi_size}),
3676 }3645 }
3677 },3646 },
3678 .immediate,
3679 .compare_flags_signed,
3680 .compare_flags_unsigned,
3681 .stack_offset,3647 .stack_offset,
3682 .memory,3648 .memory,
3683 .stack_argument_offset,3649 .stack_argument_offset,
3684 .embedded_in_code,3650 .embedded_in_code,
3685 => {3651 => {
3686 if (ty.abiSize(self.target.*) <= 4) {3652 if (abi_size <= 4) {
3687 const reg = try self.copyToTmpRegister(ty, mcv);3653 const reg = try self.copyToTmpRegister(ty, mcv);
3688 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });3654 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
3689 } else {3655 } else {
3690 return self.fail("TODO implement memcpy", .{});3656 // TODO call extern memcpy
3657 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
3658 const src_reg = regs[0];
3659 const dst_reg = regs[1];
3660 const len_reg = regs[2];
3661 const count_reg = regs[3];
3662 const tmp_reg = regs[4];
3663
3664 switch (mcv) {
3665 .stack_offset => |off| {
3666 // sub src_reg, fp, #off
3667 const adj_src_offset = off + abi_size;
3668 const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else {
3669 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3670 };
3671 _ = try self.addInst(.{
3672 .tag = .sub,
3673 .data = .{ .rr_op = .{
3674 .rd = src_reg,
3675 .rn = .fp,
3676 .op = src_offset_op,
3677 } },
3678 });
3679 },
3680 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
3681 .stack_argument_offset,
3682 .embedded_in_code,
3683 => return self.fail("TODO genSetStackArgument src={}", .{mcv}),
3684 else => unreachable,
3685 }
3686
3687 // add dst_reg, sp, #stack_offset
3688 const adj_dst_offset = stack_offset - abi_size;
3689 const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else {
3690 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3691 };
3692 _ = try self.addInst(.{
3693 .tag = .add,
3694 .data = .{ .rr_op = .{
3695 .rd = dst_reg,
3696 .rn = .sp,
3697 .op = dst_offset_op,
3698 } },
3699 });
3700
3701 // mov len, #abi_size
3702 const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(abi_size)) |x| x else {
3703 return self.fail("TODO load: set reg to elem_size with all possible sizes", .{});
3704 };
3705 _ = try self.addInst(.{
3706 .tag = .mov,
3707 .data = .{ .rr_op = .{
3708 .rd = len_reg,
3709 .rn = .r0,
3710 .op = len_op,
3711 } },
3712 });
3713
3714 // memcpy(src, dst, len)
3715 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
3691 }3716 }
3692 },3717 },
3693 .ptr_stack_offset => {3718 .compare_flags_unsigned,
3719 .compare_flags_signed,
3720 .immediate,
3721 .ptr_stack_offset,
3722 .ptr_embedded_in_code,
3723 => {
3694 const reg = try self.copyToTmpRegister(ty, mcv);3724 const reg = try self.copyToTmpRegister(ty, mcv);
3695 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });3725 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
3696 },3726 },
3697 .ptr_embedded_in_code => {
3698 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
3699 },
3700 }3727 }
3701}3728}
37023729
...@@ -4114,9 +4141,13 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4114,9 +4141,13 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4114 var stack_offset: u32 = 0;4141 var stack_offset: u32 = 0;
41154142
4116 for (param_types) |ty, i| {4143 for (param_types) |ty, i| {
4117 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*));4144 if (ty.abiSize(self.target.*) > 0) {
4118 result.args[i] = .{ .stack_argument_offset = stack_offset };4145 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*));
4119 stack_offset += @intCast(u32, ty.abiSize(self.target.*));4146 result.args[i] = .{ .stack_argument_offset = stack_offset };
4147 stack_offset += @intCast(u32, ty.abiSize(self.target.*));
4148 } else {
4149 result.args[i] = .{ .none = {} };
4150 }
4120 }4151 }
41214152
4122 result.stack_byte_count = stack_offset;4153 result.stack_byte_count = stack_offset;
test/behavior/basic.zig-3
...@@ -216,7 +216,6 @@ test "compile time global reinterpret" {...@@ -216,7 +216,6 @@ test "compile time global reinterpret" {
216}216}
217217
218test "cast undefined" {218test "cast undefined" {
219 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;219 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
221220
222 const array: [100]u8 = undefined;221 const array: [100]u8 = undefined;
...@@ -678,7 +677,6 @@ test "string concatenation" {...@@ -678,7 +677,6 @@ test "string concatenation" {
678}677}
679678
680test "thread local variable" {679test "thread local variable" {
681 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
682 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;680 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
683 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO681 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
684682
...@@ -704,7 +702,6 @@ fn maybe(x: bool) anyerror!?u32 {...@@ -704,7 +702,6 @@ fn maybe(x: bool) anyerror!?u32 {
704}702}
705703
706test "pointer to thread local array" {704test "pointer to thread local array" {
707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
708 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
709 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO706 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
710707
test/behavior/slice.zig-17
...@@ -48,7 +48,6 @@ test "slicing" {...@@ -48,7 +48,6 @@ test "slicing" {
4848
49test "const slice" {49test "const slice" {
50 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5251
53 comptime {52 comptime {
54 const a = "1234567890";53 const a = "1234567890";
...@@ -61,7 +60,6 @@ test "const slice" {...@@ -61,7 +60,6 @@ test "const slice" {
6160
62test "comptime slice of undefined pointer of length 0" {61test "comptime slice of undefined pointer of length 0" {
63 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO62 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6563
66 const slice1 = @as([*]i32, undefined)[0..0];64 const slice1 = @as([*]i32, undefined)[0..0];
67 try expect(slice1.len == 0);65 try expect(slice1.len == 0);
...@@ -83,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void {...@@ -83,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void {
8381
84test "access len index of sentinel-terminated slice" {82test "access len index of sentinel-terminated slice" {
85 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8784
88 const S = struct {85 const S = struct {
89 fn doTheTest() !void {86 fn doTheTest() !void {
...@@ -99,7 +96,6 @@ test "access len index of sentinel-terminated slice" {...@@ -99,7 +96,6 @@ test "access len index of sentinel-terminated slice" {
9996
100test "comptime slice of slice preserves comptime var" {97test "comptime slice of slice preserves comptime var" {
101 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO98 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10399
104 comptime {100 comptime {
105 var buff: [10]u8 = undefined;101 var buff: [10]u8 = undefined;
...@@ -110,7 +106,6 @@ test "comptime slice of slice preserves comptime var" {...@@ -110,7 +106,6 @@ test "comptime slice of slice preserves comptime var" {
110106
111test "slice of type" {107test "slice of type" {
112 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
114109
115 comptime {110 comptime {
116 var types_array = [_]type{ i32, f64, type };111 var types_array = [_]type{ i32, f64, type };
...@@ -151,7 +146,6 @@ fn memFree(comptime T: type, memory: []T) void {...@@ -151,7 +146,6 @@ fn memFree(comptime T: type, memory: []T) void {
151146
152test "slice of hardcoded address to pointer" {147test "slice of hardcoded address to pointer" {
153 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO148 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
155149
156 const S = struct {150 const S = struct {
157 fn doTheTest() !void {151 fn doTheTest() !void {
...@@ -168,7 +162,6 @@ test "slice of hardcoded address to pointer" {...@@ -168,7 +162,6 @@ test "slice of hardcoded address to pointer" {
168162
169test "comptime slice of pointer preserves comptime var" {163test "comptime slice of pointer preserves comptime var" {
170 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO164 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
172165
173 comptime {166 comptime {
174 var buff: [10]u8 = undefined;167 var buff: [10]u8 = undefined;
...@@ -180,7 +173,6 @@ test "comptime slice of pointer preserves comptime var" {...@@ -180,7 +173,6 @@ test "comptime slice of pointer preserves comptime var" {
180173
181test "comptime pointer cast array and then slice" {174test "comptime pointer cast array and then slice" {
182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
184176
185 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };177 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
186178
...@@ -239,7 +231,6 @@ test "slice string literal has correct type" {...@@ -239,7 +231,6 @@ test "slice string literal has correct type" {
239231
240test "result location zero sized array inside struct field implicit cast to slice" {232test "result location zero sized array inside struct field implicit cast to slice" {
241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO233 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
243234
244 const E = struct {235 const E = struct {
245 entries: []u32,236 entries: []u32,
...@@ -287,8 +278,6 @@ test "C pointer slice access" {...@@ -287,8 +278,6 @@ test "C pointer slice access" {
287}278}
288279
289test "comptime slices are disambiguated" {280test "comptime slices are disambiguated" {
290 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
291
292 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);281 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
293 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);282 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
294}283}
...@@ -343,7 +332,6 @@ test "obtaining a null terminated slice" {...@@ -343,7 +332,6 @@ test "obtaining a null terminated slice" {
343332
344test "empty array to slice" {333test "empty array to slice" {
345 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO334 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
347335
348 const S = struct {336 const S = struct {
349 fn doTheTest() !void {337 fn doTheTest() !void {
...@@ -380,7 +368,6 @@ test "@ptrCast slice to pointer" {...@@ -380,7 +368,6 @@ test "@ptrCast slice to pointer" {
380368
381test "slice syntax resulting in pointer-to-array" {369test "slice syntax resulting in pointer-to-array" {
382 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO370 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
384371
385 const S = struct {372 const S = struct {
386 fn doTheTest() !void {373 fn doTheTest() !void {
...@@ -529,7 +516,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -529,7 +516,6 @@ test "slice syntax resulting in pointer-to-array" {
529516
530test "type coercion of pointer to anon struct literal to pointer to slice" {517test "type coercion of pointer to anon struct literal to pointer to slice" {
531 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO518 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
532 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
533519
534 const S = struct {520 const S = struct {
535 const U = union {521 const U = union {
...@@ -563,7 +549,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {...@@ -563,7 +549,6 @@ test "type coercion of pointer to anon struct literal to pointer to slice" {
563549
564test "array concat of slices gives slice" {550test "array concat of slices gives slice" {
565 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO551 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
566 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
567552
568 comptime {553 comptime {
569 var a: []const u8 = "aoeu";554 var a: []const u8 = "aoeu";
...@@ -575,7 +560,6 @@ test "array concat of slices gives slice" {...@@ -575,7 +560,6 @@ test "array concat of slices gives slice" {
575560
576test "slice bounds in comptime concatenation" {561test "slice bounds in comptime concatenation" {
577 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO562 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
579563
580 const bs = comptime blk: {564 const bs = comptime blk: {
581 const b = "........1........";565 const b = "........1........";
...@@ -592,7 +576,6 @@ test "slice bounds in comptime concatenation" {...@@ -592,7 +576,6 @@ test "slice bounds in comptime concatenation" {
592576
593test "slice sentinel access at comptime" {577test "slice sentinel access at comptime" {
594 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO578 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
596579
597 {580 {
598 const str0 = &[_:0]u8{ '1', '2', '3' };581 const str0 = &[_:0]u8{ '1', '2', '3' };