diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 80b9813590..39d7f6fd8a 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -1717,6 +1717,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { const elem_ty = ptr_ty.elemType(); + const elem_size = elem_ty.abiSize(self.target.*); + switch (ptr) { .none => unreachable, .undef => unreachable, @@ -1736,17 +1738,16 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo self.register_manager.freezeRegs(&.{addr_reg}); defer self.register_manager.unfreezeRegs(&.{addr_reg}); - const abi_size = elem_ty.abiSize(self.target.*); switch (dst_mcv) { .dead => unreachable, .undef => unreachable, .compare_flags_signed, .compare_flags_unsigned => unreachable, .embedded_in_code => unreachable, .register => |dst_reg| { - try self.genLdrRegister(dst_reg, addr_reg, abi_size); + try self.genLdrRegister(dst_reg, addr_reg, elem_size); }, .stack_offset => |off| { - if (abi_size <= 8) { + if (elem_size <= 8) { const tmp_reg = try self.register_manager.allocReg(null); self.register_manager.freezeRegs(&.{tmp_reg}); 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 const tmp_reg = regs[3]; // sub dst_reg, fp, #off - const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); - const adj_off = off + elem_size; - const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{}); - _ = try self.addInst(.{ - .tag = .sub_immediate, - .data = .{ .rr_imm12_sh = .{ - .rd = dst_reg, - .rn = .x29, - .imm12 = offset, - } }, - }); + try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = off }); // mov len, #elem_size 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 }, .memory, .stack_offset, - => { - const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); - try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty); - }, .got_load, .direct_load, => { - return self.fail("TODO implement storing to {}", .{ptr}); + const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr); + try self.store(.{ .register = addr_reg }, value, ptr_ty, value_ty); }, } } @@ -3142,10 +3130,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro }, .got_load, .direct_load, - => |sym_index| { - _ = sym_index; - return self.fail("TODO implement set stack variable from {}", .{mcv}); - }, .memory, .stack_offset, => { @@ -3187,6 +3171,25 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro }); }, .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), + .got_load, + .direct_load, + => |sym_index| { + const tag: Mir.Inst.Tag = switch (mcv) { + .got_load => .load_memory_ptr_got, + .direct_load => .load_memory_ptr_direct, + else => unreachable, + }; + _ = try self.addInst(.{ + .tag = tag, + .data = .{ + .payload = try self.addExtra(Mir.LoadMemoryPie{ + .register = @enumToInt(src_reg), + .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, + .sym_index = sym_index, + }), + }, + }); + }, else => unreachable, } diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 9396744ace..31e7ea81c8 100644 --- a/src/arch/aarch64/Emit.zig +++ b/src/arch/aarch64/Emit.zig @@ -110,6 +110,8 @@ pub fn emitMir( .load_memory_got => try emit.mirLoadMemoryPie(inst), .load_memory_direct => try emit.mirLoadMemoryPie(inst), + .load_memory_ptr_got => try emit.mirLoadMemoryPie(inst), + .load_memory_ptr_direct => try emit.mirLoadMemoryPie(inst), .ldp => try emit.mirLoadStoreRegisterPair(inst), .stp => try emit.mirLoadStoreRegisterPair(inst), @@ -208,6 +210,8 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { switch (tag) { .load_memory_got, .load_memory_direct, + .load_memory_ptr_got, + .load_memory_ptr_direct, => return 2 * 4, .pop_regs, .push_regs => { const reg_list = emit.mir.instructions.items(.data)[inst].reg_list; @@ -655,12 +659,25 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { const offset = @intCast(u32, emit.code.items.len); try emit.writeInstruction(Instruction.adrp(reg, 0)); - // ldr reg, reg, offset - try emit.writeInstruction(Instruction.ldr( - reg, - reg, - Instruction.LoadStoreOffset.imm(0), - )); + switch (tag) { + .load_memory_got, + .load_memory_direct, + => { + // ldr reg, reg, offset + try emit.writeInstruction(Instruction.ldr( + reg, + reg, + Instruction.LoadStoreOffset.imm(0), + )); + }, + .load_memory_ptr_got, + .load_memory_ptr_direct, + => { + // add reg, reg, offset + try emit.writeInstruction(Instruction.add(reg, reg, 0, false)); + }, + else => unreachable, + } if (emit.bin_file.cast(link.File.MachO)) |macho_file| { 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 { .pcrel = true, .length = 2, .@"type" = switch (tag) { - .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), - .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21), + .load_memory_got, + .load_memory_ptr_got, + => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), + .load_memory_direct, + .load_memory_ptr_direct, + => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21), else => unreachable, }, }); @@ -687,8 +708,12 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void { .pcrel = false, .length = 2, .@"type" = switch (tag) { - .load_memory_got => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), - .load_memory_direct => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), + .load_memory_got, + .load_memory_ptr_got, + => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), + .load_memory_direct, + .load_memory_ptr_direct, + => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), else => unreachable, }, }); diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig index 16b25ecac8..c2ffbad422 100644 --- a/src/arch/aarch64/Mir.zig +++ b/src/arch/aarch64/Mir.zig @@ -56,10 +56,22 @@ pub const Inst = struct { dbg_line, /// Bitwise Exclusive OR (shifted register) eor_shifted_register, + /// Loads the contents into a register + /// /// Payload is `LoadMemoryPie` load_memory_got, + /// Loads the contents into a register + /// /// Payload is `LoadMemoryPie` load_memory_direct, + /// Loads the address into a register + /// + /// Payload is `LoadMemoryPie` + load_memory_ptr_got, + /// Loads the address into a register + /// + /// Payload is `LoadMemoryPie` + load_memory_ptr_direct, /// Load Pair of Registers ldp, /// Pseudo-instruction: Load from stack diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 5518d40756..5a617b84d5 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -305,7 +305,6 @@ 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 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 6c0fbd028a..024e24e400 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -48,7 +48,6 @@ const g1: i32 = 1233 + 1; var g2: i32 = 0; test "global variables" { - if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; try expect(g2 == 0); g2 = g1; try expect(g2 == 1234); @@ -604,7 +603,6 @@ test "comptime cast fn to ptr" { } test "equality compare fn ptrs" { - 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; @@ -612,7 +610,6 @@ test "equality compare fn ptrs" { } test "self reference through fn ptr field" { - 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 03cef375fe..4d76230c88 100644 --- a/test/behavior/bugs/2006.zig +++ b/test/behavior/bugs/2006.zig @@ -6,7 +6,6 @@ const S = struct { p: *S, }; test "bug 2006" { - 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 f5758a3466..980044ebfb 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1013,7 +1013,6 @@ 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 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 d6ab46e757..01d132df54 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -81,7 +81,6 @@ fn assertLenIsZero(msg: []const u8) !void { } test "access len index of sentinel-terminated slice" { - 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 99dec11bf9..5f46894fda 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -66,7 +66,6 @@ const SmallStruct = struct { }; test "lower unnamed constants" { - 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);