| author | |
| committer | |
| log | f91fe9afb92dda2b7b1ae37147ce7af40101d5ea |
| tree | 3e9743e17dab31808acbd39def65afa3aba85b51 |
| parent | 4683f94463cf7165bcaf88c8de73dd7ed5279c60 |
| signature |
9 files changed, 73 insertions(+), 41 deletions(-)
src/arch/aarch64/CodeGen.zig+26-23| ... | @@ -1717,6 +1717,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind | ... | @@ -1717,6 +1717,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind |
| 1717 | 1717 | ||
| 1718 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 1718 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1719 | const elem_ty = ptr_ty.elemType(); | 1719 | const elem_ty = ptr_ty.elemType(); |
| 1720 | const elem_size = elem_ty.abiSize(self.target.*); | ||
| 1721 | |||
| 1720 | switch (ptr) { | 1722 | switch (ptr) { |
| 1721 | .none => unreachable, | 1723 | .none => unreachable, |
| 1722 | .undef => unreachable, | 1724 | .undef => unreachable, |
| ... | @@ -1736,17 +1738,16 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1736,17 +1738,16 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1736 | self.register_manager.freezeRegs(&.{addr_reg}); | 1738 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1737 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1739 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1738 | 1740 | ||
| 1739 | const abi_size = elem_ty.abiSize(self.target.*); | ||
| 1740 | switch (dst_mcv) { | 1741 | switch (dst_mcv) { |
| 1741 | .dead => unreachable, | 1742 | .dead => unreachable, |
| 1742 | .undef => unreachable, | 1743 | .undef => unreachable, |
| 1743 | .compare_flags_signed, .compare_flags_unsigned => unreachable, | 1744 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1744 | .embedded_in_code => unreachable, | 1745 | .embedded_in_code => unreachable, |
| 1745 | .register => |dst_reg| { | 1746 | .register => |dst_reg| { |
| 1746 | try self.genLdrRegister(dst_reg, addr_reg, abi_size); | 1747 | try self.genLdrRegister(dst_reg, addr_reg, elem_size); |
| 1747 | }, | 1748 | }, |
| 1748 | .stack_offset => |off| { | 1749 | .stack_offset => |off| { |
| 1749 | if (abi_size <= 8) { | 1750 | if (elem_size <= 8) { |
| 1750 | const tmp_reg = try self.register_manager.allocReg(null); | 1751 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1751 | self.register_manager.freezeRegs(&.{tmp_reg}); | 1752 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1752 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); | 1753 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| ... | @@ -1766,17 +1767,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1766,17 +1767,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1766 | const tmp_reg = regs[3]; | 1767 | const tmp_reg = regs[3]; |
| 1767 | 1768 | ||
| 1768 | // sub dst_reg, fp, #off | 1769 | // sub dst_reg, fp, #off |
| 1769 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | 1770 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = off }); |
| 1770 | const adj_off = off + elem_size; | ||
| 1771 | const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{}); | ||
| 1772 | _ = try self.addInst(.{ | ||
| 1773 | .tag = .sub_immediate, | ||
| 1774 | .data = .{ .rr_imm12_sh = .{ | ||
| 1775 | .rd = dst_reg, | ||
| 1776 | .rn = .x29, | ||
| 1777 | .imm12 = offset, | ||
| 1778 | } }, | ||
| 1779 | }); | ||
| 1780 | 1771 | ||
| 1781 | // mov len, #elem_size | 1772 | // mov len, #elem_size |
| 1782 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = elem_size }); | 1773 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = elem_size }); |
| ... | @@ -2046,14 +2037,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2046,14 +2037,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2046 | }, | 2037 | }, |
| 2047 | .memory, | 2038 | .memory, |
| 2048 | .stack_offset, | 2039 | .stack_offset, |
| 2049 | => { | ||
| 2050 | const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); | ||
| 2051 | try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty); | ||
| 2052 | }, | ||
| 2053 | .got_load, | 2040 | .got_load, |
| 2054 | .direct_load, | 2041 | .direct_load, |
| 2055 | => { | 2042 | => { |
| 2056 | return self.fail("TODO implement storing to {}", .{ptr}); | 2043 | const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); |
| 2044 | try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty); | ||
| 2057 | }, | 2045 | }, |
| 2058 | } | 2046 | } |
| 2059 | } | 2047 | } |
| ... | @@ -3142,10 +3130,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3142,10 +3130,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3142 | }, | 3130 | }, |
| 3143 | .got_load, | 3131 | .got_load, |
| 3144 | .direct_load, | 3132 | .direct_load, |
| 3145 | => |sym_index| { | ||
| 3146 | _ = sym_index; | ||
| 3147 | return self.fail("TODO implement set stack variable from {}", .{mcv}); | ||
| 3148 | }, | ||
| 3149 | .memory, | 3133 | .memory, |
| 3150 | .stack_offset, | 3134 | .stack_offset, |
| 3151 | => { | 3135 | => { |
| ... | @@ -3187,6 +3171,25 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3187,6 +3171,25 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3187 | }); | 3171 | }); |
| 3188 | }, | 3172 | }, |
| 3189 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), | 3173 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), |
| 3174 | .got_load, | ||
| 3175 | .direct_load, | ||
| 3176 | => |sym_index| { | ||
| 3177 | const tag: Mir.Inst.Tag = switch (mcv) { | ||
| 3178 | .got_load => .load_memory_ptr_got, | ||
| 3179 | .direct_load => .load_memory_ptr_direct, | ||
| 3180 | else => unreachable, | ||
| 3181 | }; | ||
| 3182 | _ = try self.addInst(.{ | ||
| 3183 | .tag = tag, | ||
| 3184 | .data = .{ | ||
| 3185 | .payload = try self.addExtra(Mir.LoadMemoryPie{ | ||
| 3186 | .register = @enumToInt(src_reg), | ||
| 3187 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | ||
| 3188 | .sym_index = sym_index, | ||
| 3189 | }), | ||
| 3190 | }, | ||
| 3191 | }); | ||
| 3192 | }, | ||
| 3190 | else => unreachable, | 3193 | else => unreachable, |
| 3191 | } | 3194 | } |
| 3192 | 3195 |
src/arch/aarch64/Emit.zig+35-10| ... | @@ -110,6 +110,8 @@ pub fn emitMir( | ... | @@ -110,6 +110,8 @@ pub fn emitMir( |
| 110 | 110 | ||
| 111 | .load_memory_got => try emit.mirLoadMemoryPie(inst), | 111 | .load_memory_got => try emit.mirLoadMemoryPie(inst), |
| 112 | .load_memory_direct => try emit.mirLoadMemoryPie(inst), | 112 | .load_memory_direct => try emit.mirLoadMemoryPie(inst), |
| 113 | .load_memory_ptr_got => try emit.mirLoadMemoryPie(inst), | ||
| 114 | .load_memory_ptr_direct => try emit.mirLoadMemoryPie(inst), | ||
| 113 | 115 | ||
| 114 | .ldp => try emit.mirLoadStoreRegisterPair(inst), | 116 | .ldp => try emit.mirLoadStoreRegisterPair(inst), |
| 115 | .stp => try emit.mirLoadStoreRegisterPair(inst), | 117 | .stp => try emit.mirLoadStoreRegisterPair(inst), |
| ... | @@ -208,6 +210,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { | ... | @@ -208,6 +210,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 208 | switch (tag) { | 210 | switch (tag) { |
| 209 | .load_memory_got, | 211 | .load_memory_got, |
| 210 | .load_memory_direct, | 212 | .load_memory_direct, |
| 213 | .load_memory_ptr_got, | ||
| 214 | .load_memory_ptr_direct, | ||
| 211 | => return 2 * 4, | 215 | => return 2 * 4, |
| 212 | .pop_regs, .push_regs => { | 216 | .pop_regs, .push_regs => { |
| 213 | const reg_list = emit.mir.instructions.items(.data)[inst].reg_list; | 217 | const reg_list = emit.mir.instructions.items(.data)[inst].reg_list; |
| ... | @@ -655,12 +659,25 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -655,12 +659,25 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 655 | const offset = @intCast(u32, emit.code.items.len); | 659 | const offset = @intCast(u32, emit.code.items.len); |
| 656 | try emit.writeInstruction(Instruction.adrp(reg, 0)); | 660 | try emit.writeInstruction(Instruction.adrp(reg, 0)); |
| 657 | 661 | ||
| 658 | // ldr reg, reg, offset | 662 | switch (tag) { |
| 659 | try emit.writeInstruction(Instruction.ldr( | 663 | .load_memory_got, |
| 660 | reg, | 664 | .load_memory_direct, |
| 661 | reg, | 665 | => { |
| 662 | Instruction.LoadStoreOffset.imm(0), | 666 | // ldr reg, reg, offset |
| 663 | )); | 667 | try emit.writeInstruction(Instruction.ldr( |
| 668 | reg, | ||
| 669 | reg, | ||
| 670 | Instruction.LoadStoreOffset.imm(0), | ||
| 671 | )); | ||
| 672 | }, | ||
| 673 | .load_memory_ptr_got, | ||
| 674 | .load_memory_ptr_direct, | ||
| 675 | => { | ||
| 676 | // add reg, reg, offset | ||
| 677 | try emit.writeInstruction(Instruction.add(reg, reg, 0, false)); | ||
| 678 | }, | ||
| 679 | else => unreachable, | ||
| 680 | } | ||
| 664 | 681 | ||
| 665 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | 682 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 666 | const atom = macho_file.atom_by_index_table.get(data.atom_index).?; | 683 | const atom = macho_file.atom_by_index_table.get(data.atom_index).?; |
| ... | @@ -673,8 +690,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -673,8 +690,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 673 | .pcrel = true, | 690 | .pcrel = true, |
| 674 | .length = 2, | 691 | .length = 2, |
| 675 | .@"type" = switch (tag) { | 692 | .@"type" = switch (tag) { |
| 676 | .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), | 693 | .load_memory_got, |
| 677 | .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | 694 | .load_memory_ptr_got, |
| 695 | => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), | ||
| 696 | .load_memory_direct, | ||
| 697 | .load_memory_ptr_direct, | ||
| 698 | => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | ||
| 678 | else => unreachable, | 699 | else => unreachable, |
| 679 | }, | 700 | }, |
| 680 | }); | 701 | }); |
| ... | @@ -687,8 +708,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -687,8 +708,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 687 | .pcrel = false, | 708 | .pcrel = false, |
| 688 | .length = 2, | 709 | .length = 2, |
| 689 | .@"type" = switch (tag) { | 710 | .@"type" = switch (tag) { |
| 690 | .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), | 711 | .load_memory_got, |
| 691 | .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), | 712 | .load_memory_ptr_got, |
| 713 | => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), | ||
| 714 | .load_memory_direct, | ||
| 715 | .load_memory_ptr_direct, | ||
| 716 | => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), | ||
| 692 | else => unreachable, | 717 | else => unreachable, |
| 693 | }, | 718 | }, |
| 694 | }); | 719 | }); |
src/arch/aarch64/Mir.zig+12| ... | @@ -56,10 +56,22 @@ pub const Inst = struct { | ... | @@ -56,10 +56,22 @@ pub const Inst = struct { |
| 56 | dbg_line, | 56 | dbg_line, |
| 57 | /// Bitwise Exclusive OR (shifted register) | 57 | /// Bitwise Exclusive OR (shifted register) |
| 58 | eor_shifted_register, | 58 | eor_shifted_register, |
| 59 | /// Loads the contents into a register | ||
| 60 | /// | ||
| 59 | /// Payload is `LoadMemoryPie` | 61 | /// Payload is `LoadMemoryPie` |
| 60 | load_memory_got, | 62 | load_memory_got, |
| 63 | /// Loads the contents into a register | ||
| 64 | /// | ||
| 61 | /// Payload is `LoadMemoryPie` | 65 | /// Payload is `LoadMemoryPie` |
| 62 | load_memory_direct, | 66 | load_memory_direct, |
| 67 | /// Loads the address into a register | ||
| 68 | /// | ||
| 69 | /// Payload is `LoadMemoryPie` | ||
| 70 | load_memory_ptr_got, | ||
| 71 | /// Loads the address into a register | ||
| 72 | /// | ||
| 73 | /// Payload is `LoadMemoryPie` | ||
| 74 | load_memory_ptr_direct, | ||
| 63 | /// Load Pair of Registers | 75 | /// Load Pair of Registers |
| 64 | ldp, | 76 | ldp, |
| 65 | /// Pseudo-instruction: Load from stack | 77 | /// Pseudo-instruction: Load from stack |
test/behavior/align.zig-1| ... | @@ -305,7 +305,6 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { | ... | @@ -305,7 +305,6 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | test "alignment of function with c calling convention" { | 307 | test "alignment of function with c calling convention" { |
| 308 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 309 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 308 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 310 | 309 | ||
| 311 | var runtime_nothing = &nothing; | 310 | var runtime_nothing = &nothing; |
test/behavior/basic.zig-3| ... | @@ -48,7 +48,6 @@ const g1: i32 = 1233 + 1; | ... | @@ -48,7 +48,6 @@ const g1: i32 = 1233 + 1; |
| 48 | var g2: i32 = 0; | 48 | var g2: i32 = 0; |
| 49 | 49 | ||
| 50 | test "global variables" { | 50 | test "global variables" { |
| 51 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 52 | try expect(g2 == 0); | 51 | try expect(g2 == 0); |
| 53 | g2 = g1; | 52 | g2 = g1; |
| 54 | try expect(g2 == 1234); | 53 | try expect(g2 == 1234); |
| ... | @@ -604,7 +603,6 @@ test "comptime cast fn to ptr" { | ... | @@ -604,7 +603,6 @@ test "comptime cast fn to ptr" { |
| 604 | } | 603 | } |
| 605 | 604 | ||
| 606 | test "equality compare fn ptrs" { | 605 | test "equality compare fn ptrs" { |
| 607 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 608 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 606 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 609 | 607 | ||
| 610 | var a = &emptyFn; | 608 | var a = &emptyFn; |
| ... | @@ -612,7 +610,6 @@ test "equality compare fn ptrs" { | ... | @@ -612,7 +610,6 @@ test "equality compare fn ptrs" { |
| 612 | } | 610 | } |
| 613 | 611 | ||
| 614 | test "self reference through fn ptr field" { | 612 | test "self reference through fn ptr field" { |
| 615 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 616 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 613 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 617 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 614 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 618 | 615 |
test/behavior/bugs/2006.zig-1| ... | @@ -6,7 +6,6 @@ const S = struct { | ... | @@ -6,7 +6,6 @@ const S = struct { |
| 6 | p: *S, | 6 | p: *S, |
| 7 | }; | 7 | }; |
| 8 | test "bug 2006" { | 8 | test "bug 2006" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 11 | var a: S = undefined; | 10 | var a: S = undefined; |
| 12 | a = S{ .p = undefined }; | 11 | a = S{ .p = undefined }; |
test/behavior/cast.zig-1| ... | @@ -1013,7 +1013,6 @@ test "cast from array reference to fn: comptime fn ptr" { | ... | @@ -1013,7 +1013,6 @@ test "cast from array reference to fn: comptime fn ptr" { |
| 1013 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1013 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1014 | } | 1014 | } |
| 1015 | test "cast from array reference to fn: runtime fn ptr" { | 1015 | test "cast from array reference to fn: runtime fn ptr" { |
| 1016 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 1017 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1016 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1018 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1017 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1019 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1018 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
test/behavior/slice.zig-1| ... | @@ -81,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void { | ... | @@ -81,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void { |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | test "access len index of sentinel-terminated slice" { | 83 | test "access len index of sentinel-terminated slice" { |
| 84 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 85 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 84 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 86 | 85 | ||
| 87 | const S = struct { | 86 | const S = struct { |
test/behavior/struct.zig-1| ... | @@ -66,7 +66,6 @@ const SmallStruct = struct { | ... | @@ -66,7 +66,6 @@ const SmallStruct = struct { |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | test "lower unnamed constants" { | 68 | test "lower unnamed constants" { |
| 69 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | ||
| 70 | var foo = SmallStruct{ .a = 1, .b = 255 }; | 69 | var foo = SmallStruct{ .a = 1, .b = 255 }; |
| 71 | try expect(foo.first() == 1); | 70 | try expect(foo.first() == 1); |
| 72 | try expect(foo.second() == 255); | 71 | try expect(foo.second() == 255); |