From 25f73224f7f9921633e67d4b5ef12c6ec10406eb Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Mon, 21 Feb 2022 00:56:47 +0100 Subject: [PATCH] stage2 AArch64: pass a few more behavior tests --- src/arch/aarch64/CodeGen.zig | 75 +++++++++++++++++++++++++----------- test/behavior/align.zig | 2 +- test/behavior/basic.zig | 4 +- test/behavior/bugs/2006.zig | 2 +- test/behavior/cast.zig | 2 +- test/behavior/slice.zig | 2 +- test/behavior/struct.zig | 4 +- 7 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 0f013ae673..062a5f5748 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -2079,7 +2079,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { return if (self.liveness.isUnused(inst)) .dead else result: { const mcv = try self.resolveInst(operand); - const struct_ty = self.air.typeOf(operand).childType(); + const ptr_ty = self.air.typeOf(operand); + const struct_ty = ptr_ty.childType(); const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); const struct_field_ty = struct_ty.structFieldType(index); @@ -2088,7 +2089,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde .ptr_stack_offset => |off| { break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; }, - else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), + else => { + const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ + .immediate = struct_field_offset, + }); + self.register_manager.freezeRegs(&.{offset_reg}); + defer self.register_manager.unfreezeRegs(&.{offset_reg}); + + const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv); + self.register_manager.freezeRegs(&.{addr_reg}); + defer self.register_manager.unfreezeRegs(&.{addr_reg}); + + const dest = try self.binOp( + .add, + null, + .{ .register = addr_reg }, + .{ .register = offset_reg }, + Type.usize, + Type.usize, + ); + + break :result dest; + }, } }; } @@ -3117,17 +3139,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro _ = sym_index; return self.fail("TODO implement set stack variable from {}", .{mcv}); }, - .memory => |vaddr| { - _ = vaddr; - return self.fail("TODO implement set stack variable from memory vaddr", .{}); - }, - .stack_offset => |off| { - if (stack_offset == off) - return; // Copy stack variable to itself; nothing to do. + .memory, + .stack_offset, + => { + switch (mcv) { + .stack_offset => |off| { + if (stack_offset == off) + return; // Copy stack variable to itself; nothing to do. + }, + else => {}, + } - const ptr_bits = self.target.cpu.arch.ptrBitWidth(); - const ptr_bytes: u64 = @divExact(ptr_bits, 8); - if (abi_size <= ptr_bytes) { + if (abi_size <= 8) { const reg = try self.copyToTmpRegister(ty, mcv); return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); } else { @@ -3142,17 +3165,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro const count_reg = regs[3]; const tmp_reg = regs[4]; - // sub src_reg, fp, #off - const adj_src_offset = off + abi_size; - const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); - _ = try self.addInst(.{ - .tag = .sub_immediate, - .data = .{ .rr_imm12_sh = .{ - .rd = src_reg, - .rn = .x29, - .imm12 = src_offset, - } }, - }); + switch (mcv) { + .stack_offset => |off| { + // sub src_reg, fp, #off + const adj_src_offset = off + abi_size; + const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); + _ = try self.addInst(.{ + .tag = .sub_immediate, + .data = .{ .rr_imm12_sh = .{ + .rd = src_reg, + .rn = .x29, + .imm12 = src_offset, + } }, + }); + }, + .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), + else => unreachable, + } // sub dst_reg, fp, #stack_offset const adj_dst_off = stack_offset + abi_size; diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 98a18c5b3b..6a899fcdc5 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -311,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { } test "alignment of function with c calling convention" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; var runtime_nothing = ¬hing; diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 873e41827f..d5081ca636 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -610,7 +610,7 @@ test "comptime cast fn to ptr" { } test "equality compare fn ptrs" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; var a = &emptyFn; @@ -618,7 +618,7 @@ test "equality compare fn ptrs" { } test "self reference through fn ptr field" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; diff --git a/test/behavior/bugs/2006.zig b/test/behavior/bugs/2006.zig index fcacb9a2c6..03cef375fe 100644 --- a/test/behavior/bugs/2006.zig +++ b/test/behavior/bugs/2006.zig @@ -6,7 +6,7 @@ const S = struct { p: *S, }; test "bug 2006" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; var a: S = undefined; a = S{ .p = undefined }; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index b234255600..f5758a3466 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1013,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" { try expect(@ptrToInt(f) == @ptrToInt(&global_array)); } test "cast from array reference to fn: runtime fn ptr" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 08ab0edf48..5123350e20 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void { } test "access len index of sentinel-terminated slice" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO const S = struct { diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 3e92b4374b..c85f05e4ff 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -43,7 +43,6 @@ const StructWithFields = struct { }; test "non-packed struct has fields padded out to the required alignment" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 }; @@ -67,7 +66,7 @@ const SmallStruct = struct { }; test "lower unnamed constants" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; var foo = SmallStruct{ .a = 1, .b = 255 }; try expect(foo.first() == 1); try expect(foo.second() == 255); @@ -186,7 +185,6 @@ test "store member function in variable" { } test "member functions" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; const r = MemberFnRand{ .seed = 1234 }; try expect(r.getSeed() == 1234); }