| 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 | 1717 | |
| 1718 | 1718 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1719 | 1719 | const elem_ty = ptr_ty.elemType(); |
| 1720 | const elem_size = elem_ty.abiSize(self.target.*); | |
| 1721 | ||
| 1720 | 1722 | switch (ptr) { |
| 1721 | 1723 | .none => unreachable, |
| 1722 | 1724 | .undef => unreachable, |
| ... | ... | @@ -1736,17 +1738,16 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1736 | 1738 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1737 | 1739 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1738 | 1740 | |
| 1739 | const abi_size = elem_ty.abiSize(self.target.*); | |
| 1740 | 1741 | switch (dst_mcv) { |
| 1741 | 1742 | .dead => unreachable, |
| 1742 | 1743 | .undef => unreachable, |
| 1743 | 1744 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1744 | 1745 | .embedded_in_code => unreachable, |
| 1745 | 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 | 1749 | .stack_offset => |off| { |
| 1749 | if (abi_size <= 8) { | |
| 1750 | if (elem_size <= 8) { | |
| 1750 | 1751 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1751 | 1752 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1752 | 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 | 1767 | const tmp_reg = regs[3]; |
| 1767 | 1768 | |
| 1768 | 1769 | // sub dst_reg, fp, #off |
| 1769 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | |
| 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 | }); | |
| 1770 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = off }); | |
| 1780 | 1771 | |
| 1781 | 1772 | // mov len, #elem_size |
| 1782 | 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 | 2037 | }, |
| 2047 | 2038 | .memory, |
| 2048 | 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 | 2040 | .got_load, |
| 2054 | 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 | 3130 | }, |
| 3143 | 3131 | .got_load, |
| 3144 | 3132 | .direct_load, |
| 3145 | => |sym_index| { | |
| 3146 | _ = sym_index; | |
| 3147 | return self.fail("TODO implement set stack variable from {}", .{mcv}); | |
| 3148 | }, | |
| 3149 | 3133 | .memory, |
| 3150 | 3134 | .stack_offset, |
| 3151 | 3135 | => { |
| ... | ... | @@ -3187,6 +3171,25 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3187 | 3171 | }); |
| 3188 | 3172 | }, |
| 3189 | 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 | 3193 | else => unreachable, |
| 3191 | 3194 | } |
| 3192 | 3195 |
src/arch/aarch64/Emit.zig+35-10| ... | ... | @@ -110,6 +110,8 @@ pub fn emitMir( |
| 110 | 110 | |
| 111 | 111 | .load_memory_got => try emit.mirLoadMemoryPie(inst), |
| 112 | 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 | 116 | .ldp => try emit.mirLoadStoreRegisterPair(inst), |
| 115 | 117 | .stp => try emit.mirLoadStoreRegisterPair(inst), |
| ... | ... | @@ -208,6 +210,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 208 | 210 | switch (tag) { |
| 209 | 211 | .load_memory_got, |
| 210 | 212 | .load_memory_direct, |
| 213 | .load_memory_ptr_got, | |
| 214 | .load_memory_ptr_direct, | |
| 211 | 215 | => return 2 * 4, |
| 212 | 216 | .pop_regs, .push_regs => { |
| 213 | 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 | 659 | const offset = @intCast(u32, emit.code.items.len); |
| 656 | 660 | try emit.writeInstruction(Instruction.adrp(reg, 0)); |
| 657 | 661 | |
| 658 | // ldr reg, reg, offset | |
| 659 | try emit.writeInstruction(Instruction.ldr( | |
| 660 | reg, | |
| 661 | reg, | |
| 662 | Instruction.LoadStoreOffset.imm(0), | |
| 663 | )); | |
| 662 | switch (tag) { | |
| 663 | .load_memory_got, | |
| 664 | .load_memory_direct, | |
| 665 | => { | |
| 666 | // ldr reg, reg, offset | |
| 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 | 682 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 666 | 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 | 690 | .pcrel = true, |
| 674 | 691 | .length = 2, |
| 675 | 692 | .@"type" = switch (tag) { |
| 676 | .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), | |
| 677 | .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | |
| 693 | .load_memory_got, | |
| 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 | 699 | else => unreachable, |
| 679 | 700 | }, |
| 680 | 701 | }); |
| ... | ... | @@ -687,8 +708,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 687 | 708 | .pcrel = false, |
| 688 | 709 | .length = 2, |
| 689 | 710 | .@"type" = switch (tag) { |
| 690 | .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), | |
| 691 | .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), | |
| 711 | .load_memory_got, | |
| 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 | 717 | else => unreachable, |
| 693 | 718 | }, |
| 694 | 719 | }); |
src/arch/aarch64/Mir.zig+12| ... | ... | @@ -56,10 +56,22 @@ pub const Inst = struct { |
| 56 | 56 | dbg_line, |
| 57 | 57 | /// Bitwise Exclusive OR (shifted register) |
| 58 | 58 | eor_shifted_register, |
| 59 | /// Loads the contents into a register | |
| 60 | /// | |
| 59 | 61 | /// Payload is `LoadMemoryPie` |
| 60 | 62 | load_memory_got, |
| 63 | /// Loads the contents into a register | |
| 64 | /// | |
| 61 | 65 | /// Payload is `LoadMemoryPie` |
| 62 | 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 | 75 | /// Load Pair of Registers |
| 64 | 76 | ldp, |
| 65 | 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 | 305 | } |
| 306 | 306 | |
| 307 | 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 | 308 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 310 | 309 | |
| 311 | 310 | var runtime_nothing = &nothing; |
test/behavior/basic.zig-3| ... | ... | @@ -48,7 +48,6 @@ const g1: i32 = 1233 + 1; |
| 48 | 48 | var g2: i32 = 0; |
| 49 | 49 | |
| 50 | 50 | test "global variables" { |
| 51 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 52 | 51 | try expect(g2 == 0); |
| 53 | 52 | g2 = g1; |
| 54 | 53 | try expect(g2 == 1234); |
| ... | ... | @@ -604,7 +603,6 @@ test "comptime cast fn to ptr" { |
| 604 | 603 | } |
| 605 | 604 | |
| 606 | 605 | test "equality compare fn ptrs" { |
| 607 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 608 | 606 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 609 | 607 | |
| 610 | 608 | var a = &emptyFn; |
| ... | ... | @@ -612,7 +610,6 @@ test "equality compare fn ptrs" { |
| 612 | 610 | } |
| 613 | 611 | |
| 614 | 612 | test "self reference through fn ptr field" { |
| 615 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 616 | 613 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 617 | 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 | 6 | p: *S, |
| 7 | 7 | }; |
| 8 | 8 | test "bug 2006" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 10 | 9 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 11 | 10 | var a: S = undefined; |
| 12 | 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 | 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 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 1017 | 1016 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1018 | 1017 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1019 | 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 | 81 | } |
| 82 | 82 | |
| 83 | 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 | 84 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 86 | 85 | |
| 87 | 86 | const S = struct { |
test/behavior/struct.zig-1| ... | ... | @@ -66,7 +66,6 @@ const SmallStruct = struct { |
| 66 | 66 | }; |
| 67 | 67 | |
| 68 | 68 | test "lower unnamed constants" { |
| 69 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; | |
| 70 | 69 | var foo = SmallStruct{ .a = 1, .b = 255 }; |
| 71 | 70 | try expect(foo.first() == 1); |
| 72 | 71 | try expect(foo.second() == 255); |