| author | |
| committer | |
| log | 25f73224f7f9921633e67d4b5ef12c6ec10406eb |
| tree | ecdaa6426a045247fa17e591edb7af7700be147d |
| parent | 2ba1ef165aa3fb5da40d05fed9a120630b2529d2 |
| signature |
7 files changed, 59 insertions(+), 32 deletions(-)
src/arch/aarch64/CodeGen.zig+52-23| ... | ... | @@ -2079,7 +2079,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 2079 | 2079 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 2080 | 2080 | return if (self.liveness.isUnused(inst)) .dead else result: { |
| 2081 | 2081 | const mcv = try self.resolveInst(operand); |
| 2082 | const struct_ty = self.air.typeOf(operand).childType(); | |
| 2082 | const ptr_ty = self.air.typeOf(operand); | |
| 2083 | const struct_ty = ptr_ty.childType(); | |
| 2083 | 2084 | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 2084 | 2085 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 2085 | 2086 | 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 |
| 2088 | 2089 | .ptr_stack_offset => |off| { |
| 2089 | 2090 | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; |
| 2090 | 2091 | }, |
| 2091 | else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), | |
| 2092 | else => { | |
| 2093 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ | |
| 2094 | .immediate = struct_field_offset, | |
| 2095 | }); | |
| 2096 | self.register_manager.freezeRegs(&.{offset_reg}); | |
| 2097 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); | |
| 2098 | ||
| 2099 | const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv); | |
| 2100 | self.register_manager.freezeRegs(&.{addr_reg}); | |
| 2101 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | |
| 2102 | ||
| 2103 | const dest = try self.binOp( | |
| 2104 | .add, | |
| 2105 | null, | |
| 2106 | .{ .register = addr_reg }, | |
| 2107 | .{ .register = offset_reg }, | |
| 2108 | Type.usize, | |
| 2109 | Type.usize, | |
| 2110 | ); | |
| 2111 | ||
| 2112 | break :result dest; | |
| 2113 | }, | |
| 2092 | 2114 | } |
| 2093 | 2115 | }; |
| 2094 | 2116 | } |
| ... | ... | @@ -3117,17 +3139,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3117 | 3139 | _ = sym_index; |
| 3118 | 3140 | return self.fail("TODO implement set stack variable from {}", .{mcv}); |
| 3119 | 3141 | }, |
| 3120 | .memory => |vaddr| { | |
| 3121 | _ = vaddr; | |
| 3122 | return self.fail("TODO implement set stack variable from memory vaddr", .{}); | |
| 3123 | }, | |
| 3124 | .stack_offset => |off| { | |
| 3125 | if (stack_offset == off) | |
| 3126 | return; // Copy stack variable to itself; nothing to do. | |
| 3142 | .memory, | |
| 3143 | .stack_offset, | |
| 3144 | => { | |
| 3145 | switch (mcv) { | |
| 3146 | .stack_offset => |off| { | |
| 3147 | if (stack_offset == off) | |
| 3148 | return; // Copy stack variable to itself; nothing to do. | |
| 3149 | }, | |
| 3150 | else => {}, | |
| 3151 | } | |
| 3127 | 3152 | |
| 3128 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 3129 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 3130 | if (abi_size <= ptr_bytes) { | |
| 3153 | if (abi_size <= 8) { | |
| 3131 | 3154 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3132 | 3155 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3133 | 3156 | } else { |
| ... | ... | @@ -3142,17 +3165,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3142 | 3165 | const count_reg = regs[3]; |
| 3143 | 3166 | const tmp_reg = regs[4]; |
| 3144 | 3167 | |
| 3145 | // sub src_reg, fp, #off | |
| 3146 | const adj_src_offset = off + abi_size; | |
| 3147 | const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); | |
| 3148 | _ = try self.addInst(.{ | |
| 3149 | .tag = .sub_immediate, | |
| 3150 | .data = .{ .rr_imm12_sh = .{ | |
| 3151 | .rd = src_reg, | |
| 3152 | .rn = .x29, | |
| 3153 | .imm12 = src_offset, | |
| 3154 | } }, | |
| 3155 | }); | |
| 3168 | switch (mcv) { | |
| 3169 | .stack_offset => |off| { | |
| 3170 | // sub src_reg, fp, #off | |
| 3171 | const adj_src_offset = off + abi_size; | |
| 3172 | const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); | |
| 3173 | _ = try self.addInst(.{ | |
| 3174 | .tag = .sub_immediate, | |
| 3175 | .data = .{ .rr_imm12_sh = .{ | |
| 3176 | .rd = src_reg, | |
| 3177 | .rn = .x29, | |
| 3178 | .imm12 = src_offset, | |
| 3179 | } }, | |
| 3180 | }); | |
| 3181 | }, | |
| 3182 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), | |
| 3183 | else => unreachable, | |
| 3184 | } | |
| 3156 | 3185 | |
| 3157 | 3186 | // sub dst_reg, fp, #stack_offset |
| 3158 | 3187 | const adj_dst_off = stack_offset + abi_size; |
test/behavior/align.zig+1-1| ... | ... | @@ -311,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | 313 | test "alignment of function with c calling convention" { |
| 314 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 314 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 315 | 315 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 316 | 316 | |
| 317 | 317 | var runtime_nothing = &nothing; |
test/behavior/basic.zig+2-2| ... | ... | @@ -610,7 +610,7 @@ test "comptime cast fn to ptr" { |
| 610 | 610 | } |
| 611 | 611 | |
| 612 | 612 | test "equality compare fn ptrs" { |
| 613 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 613 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 614 | 614 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 615 | 615 | |
| 616 | 616 | var a = &emptyFn; |
| ... | ... | @@ -618,7 +618,7 @@ test "equality compare fn ptrs" { |
| 618 | 618 | } |
| 619 | 619 | |
| 620 | 620 | test "self reference through fn ptr field" { |
| 621 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 621 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 622 | 622 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 623 | 623 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 624 | 624 |
test/behavior/bugs/2006.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const S = struct { |
| 6 | 6 | p: *S, |
| 7 | 7 | }; |
| 8 | 8 | test "bug 2006" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 9 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 10 | 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 11 | 11 | var a: S = undefined; |
| 12 | 12 | a = S{ .p = undefined }; |
test/behavior/cast.zig+1-1| ... | ... | @@ -1013,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" { |
| 1013 | 1013 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1014 | 1014 | } |
| 1015 | 1015 | test "cast from array reference to fn: runtime fn ptr" { |
| 1016 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1016 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 1017 | 1017 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1018 | 1018 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1019 | 1019 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
test/behavior/slice.zig+1-1| ... | ... | @@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void { |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | test "access len index of sentinel-terminated slice" { |
| 84 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 84 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 85 | 85 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 86 | 86 | |
| 87 | 87 | const S = struct { |
test/behavior/struct.zig+1-3| ... | ... | @@ -43,7 +43,6 @@ const StructWithFields = struct { |
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | 45 | test "non-packed struct has fields padded out to the required alignment" { |
| 46 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 47 | 46 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 48 | 47 | |
| 49 | 48 | const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 }; |
| ... | ... | @@ -67,7 +66,7 @@ const SmallStruct = struct { |
| 67 | 66 | }; |
| 68 | 67 | |
| 69 | 68 | test "lower unnamed constants" { |
| 70 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 69 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 71 | 70 | var foo = SmallStruct{ .a = 1, .b = 255 }; |
| 72 | 71 | try expect(foo.first() == 1); |
| 73 | 72 | try expect(foo.second() == 255); |
| ... | ... | @@ -186,7 +185,6 @@ test "store member function in variable" { |
| 186 | 185 | } |
| 187 | 186 | |
| 188 | 187 | test "member functions" { |
| 189 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 190 | 188 | const r = MemberFnRand{ .seed = 1234 }; |
| 191 | 189 | try expect(r.getSeed() == 1234); |
| 192 | 190 | } |