| ... | ... | @@ -3569,7 +3569,12 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3569 | 3569 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{}); |
| 3570 | 3570 | } |
| 3571 | 3571 | |
| 3572 | | try self.genInlineMemcpy(dst_mcv, ptr, .{ .immediate = abi_size }, .{}); |
| 3572 | try self.genInlineMemcpy( |
| 3573 | .{ .ptr_stack_offset = off }, |
| 3574 | ptr, |
| 3575 | .{ .immediate = abi_size }, |
| 3576 | .{}, |
| 3577 | ); |
| 3573 | 3578 | }, |
| 3574 | 3579 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| 3575 | 3580 | } |
| ... | ... | @@ -3745,22 +3750,47 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3745 | 3750 | -@intCast(i32, overflow_bit_offset), |
| 3746 | 3751 | ); |
| 3747 | 3752 | }, |
| 3748 | | .linker_load, .memory, .stack_offset => if (abi_size <= 8) { |
| 3753 | .memory, .linker_load => if (abi_size <= 8) { |
| 3754 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3755 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3756 | defer self.register_manager.unlockReg(tmp_lock); |
| 3757 | |
| 3758 | try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 3759 | } else { |
| 3760 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 3761 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 3762 | defer self.register_manager.unlockReg(addr_lock); |
| 3763 | |
| 3764 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, value); |
| 3765 | try self.genInlineMemcpy( |
| 3766 | ptr, |
| 3767 | .{ .register = addr_reg }, |
| 3768 | .{ .immediate = abi_size }, |
| 3769 | .{}, |
| 3770 | ); |
| 3771 | }, |
| 3772 | .stack_offset => |off| if (abi_size <= 8) { |
| 3749 | 3773 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3774 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3775 | defer self.register_manager.unlockReg(tmp_lock); |
| 3776 | |
| 3750 | 3777 | try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 3751 | 3778 | } else try self.genInlineMemcpy( |
| 3752 | | .{ .stack_offset = 0 }, |
| 3753 | | value, |
| 3779 | ptr, |
| 3780 | .{ .ptr_stack_offset = off }, |
| 3754 | 3781 | .{ .immediate = abi_size }, |
| 3755 | | .{ .source_stack_base = .rbp, .dest_stack_base = reg.to64() }, |
| 3782 | .{}, |
| 3756 | 3783 | ), |
| 3757 | 3784 | .ptr_stack_offset => { |
| 3758 | 3785 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); |
| 3786 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3787 | defer self.register_manager.unlockReg(tmp_lock); |
| 3788 | |
| 3759 | 3789 | try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 3760 | 3790 | }, |
| 3761 | 3791 | } |
| 3762 | 3792 | }, |
| 3763 | | .linker_load, .memory => { |
| 3793 | .memory, .linker_load => { |
| 3764 | 3794 | const value_lock: ?RegisterLock = switch (value) { |
| 3765 | 3795 | .register => |reg| self.register_manager.lockReg(reg), |
| 3766 | 3796 | else => null, |
| ... | ... | @@ -5530,14 +5560,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 5530 | 5560 | assert(ret_ty.isError()); |
| 5531 | 5561 | }, |
| 5532 | 5562 | .stack_offset => { |
| 5533 | | const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv); |
| 5534 | | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 5535 | | defer self.register_manager.unlockReg(reg_lock); |
| 5536 | | |
| 5537 | | try self.genSetStack(ret_ty, 0, operand, .{ |
| 5538 | | .source_stack_base = .rbp, |
| 5539 | | .dest_stack_base = reg, |
| 5540 | | }); |
| 5563 | try self.store(self.ret_mcv, operand, Type.usize, ret_ty); |
| 5541 | 5564 | }, |
| 5542 | 5565 | else => { |
| 5543 | 5566 | try self.setRegOrMem(ret_ty, self.ret_mcv, operand); |
| ... | ... | @@ -5556,6 +5579,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5556 | 5579 | const ptr = try self.resolveInst(un_op); |
| 5557 | 5580 | const ptr_ty = self.air.typeOf(un_op); |
| 5558 | 5581 | const elem_ty = ptr_ty.elemType(); |
| 5582 | const abi_size = elem_ty.abiSize(self.target.*); |
| 5559 | 5583 | switch (self.ret_mcv) { |
| 5560 | 5584 | .immediate => { |
| 5561 | 5585 | assert(elem_ty.isError()); |
| ... | ... | @@ -5565,10 +5589,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5565 | 5589 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 5566 | 5590 | defer self.register_manager.unlockReg(reg_lock); |
| 5567 | 5591 | |
| 5568 | | try self.genInlineMemcpy(.{ .stack_offset = 0 }, ptr, .{ .immediate = elem_ty.abiSize(self.target.*) }, .{ |
| 5569 | | .source_stack_base = .rbp, |
| 5570 | | .dest_stack_base = reg, |
| 5571 | | }); |
| 5592 | try self.genInlineMemcpy(.{ .register = reg }, ptr, .{ .immediate = abi_size }, .{}); |
| 5572 | 5593 | }, |
| 5573 | 5594 | else => { |
| 5574 | 5595 | try self.load(self.ret_mcv, ptr, ptr_ty); |
| ... | ... | @@ -6838,7 +6859,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 6838 | 6859 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 6839 | 6860 | } |
| 6840 | 6861 | try self.genInlineMemset( |
| 6841 | | .{ .stack_offset = stack_offset }, |
| 6862 | .{ .ptr_stack_offset = stack_offset }, |
| 6842 | 6863 | .{ .immediate = 0xaa }, |
| 6843 | 6864 | .{ .immediate = abi_size }, |
| 6844 | 6865 | .{ .dest_stack_base = .rsp }, |
| ... | ... | @@ -6877,10 +6898,17 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 6877 | 6898 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 6878 | 6899 | } |
| 6879 | 6900 | |
| 6880 | | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, .{ |
| 6881 | | .source_stack_base = .rbp, |
| 6882 | | .dest_stack_base = .rsp, |
| 6883 | | }); |
| 6901 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 6902 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6903 | defer self.register_manager.unlockReg(addr_lock); |
| 6904 | |
| 6905 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, mcv); |
| 6906 | try self.genInlineMemcpy( |
| 6907 | .{ .ptr_stack_offset = stack_offset }, |
| 6908 | .{ .register = addr_reg }, |
| 6909 | .{ .immediate = abi_size }, |
| 6910 | .{ .dest_stack_base = .rsp }, |
| 6911 | ); |
| 6884 | 6912 | }, |
| 6885 | 6913 | .register => |reg| { |
| 6886 | 6914 | switch (ty.zigTypeTag()) { |
| ... | ... | @@ -6920,16 +6948,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 6920 | 6948 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 6921 | 6949 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 6922 | 6950 | }, |
| 6923 | | .stack_offset => { |
| 6951 | .stack_offset => |mcv_off| { |
| 6924 | 6952 | if (abi_size <= 8) { |
| 6925 | 6953 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 6926 | 6954 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 6927 | 6955 | } |
| 6928 | 6956 | |
| 6929 | | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, .{ |
| 6930 | | .source_stack_base = .rbp, |
| 6931 | | .dest_stack_base = .rsp, |
| 6932 | | }); |
| 6957 | try self.genInlineMemcpy( |
| 6958 | .{ .ptr_stack_offset = stack_offset }, |
| 6959 | .{ .ptr_stack_offset = mcv_off }, |
| 6960 | .{ .immediate = abi_size }, |
| 6961 | .{ .dest_stack_base = .rsp }, |
| 6962 | ); |
| 6933 | 6963 | }, |
| 6934 | 6964 | } |
| 6935 | 6965 | } |
| ... | ... | @@ -6963,7 +6993,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 6963 | 6993 | opts, |
| 6964 | 6994 | ), |
| 6965 | 6995 | else => |x| return self.genInlineMemset( |
| 6966 | | .{ .stack_offset = stack_offset }, |
| 6996 | .{ .ptr_stack_offset = stack_offset }, |
| 6967 | 6997 | .{ .immediate = 0xaa }, |
| 6968 | 6998 | .{ .immediate = x }, |
| 6969 | 6999 | opts, |
| ... | ... | @@ -7072,22 +7102,40 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 7072 | 7102 | }, |
| 7073 | 7103 | } |
| 7074 | 7104 | }, |
| 7075 | | .memory, .linker_load, .stack_offset, .ptr_stack_offset => { |
| 7076 | | switch (mcv) { |
| 7077 | | else => unreachable, |
| 7078 | | .memory, .linker_load, .ptr_stack_offset => {}, |
| 7079 | | .stack_offset => |src_off| if (stack_offset == src_off) { |
| 7080 | | // Copy stack variable to itself; nothing to do. |
| 7081 | | return; |
| 7082 | | }, |
| 7083 | | } |
| 7105 | .memory, .linker_load => if (abi_size <= 8) { |
| 7106 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7107 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 7108 | } else { |
| 7109 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 7110 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7111 | defer self.register_manager.unlockReg(addr_lock); |
| 7084 | 7112 | |
| 7085 | | if (abi_size <= 8) { |
| 7086 | | const reg = try self.copyToTmpRegister(ty, mcv); |
| 7087 | | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 7088 | | } |
| 7113 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, mcv); |
| 7114 | try self.genInlineMemcpy( |
| 7115 | .{ .ptr_stack_offset = stack_offset }, |
| 7116 | .{ .register = addr_reg }, |
| 7117 | .{ .immediate = abi_size }, |
| 7118 | .{}, |
| 7119 | ); |
| 7120 | }, |
| 7121 | .stack_offset => |off| if (abi_size <= 8) { |
| 7122 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7123 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7124 | defer self.register_manager.unlockReg(tmp_lock); |
| 7089 | 7125 | |
| 7090 | | try self.genInlineMemcpy(.{ .stack_offset = stack_offset }, mcv, .{ .immediate = abi_size }, opts); |
| 7126 | try self.genSetStack(ty, stack_offset, .{ .register = tmp_reg }, opts); |
| 7127 | } else try self.genInlineMemcpy( |
| 7128 | .{ .ptr_stack_offset = stack_offset }, |
| 7129 | .{ .ptr_stack_offset = off }, |
| 7130 | .{ .immediate = abi_size }, |
| 7131 | .{}, |
| 7132 | ), |
| 7133 | .ptr_stack_offset => { |
| 7134 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); |
| 7135 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7136 | defer self.register_manager.unlockReg(tmp_lock); |
| 7137 | |
| 7138 | try self.genSetStack(ty, stack_offset, .{ .register = tmp_reg }, opts); |
| 7091 | 7139 | }, |
| 7092 | 7140 | } |
| 7093 | 7141 | } |
| ... | ... | @@ -7134,10 +7182,14 @@ fn genInlineMemcpyRegisterRegister( |
| 7134 | 7182 | next_offset -= nearest_power_of_two; |
| 7135 | 7183 | } |
| 7136 | 7184 | } else { |
| 7137 | | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 7138 | | .base = dst_reg, |
| 7139 | | .disp = -offset, |
| 7140 | | }), registerAlias(src_reg, abi_size)); |
| 7185 | try self.asmMemoryRegister( |
| 7186 | switch (src_reg.class()) { |
| 7187 | .general_purpose, .segment => .mov, |
| 7188 | .floating_point => .movss, |
| 7189 | }, |
| 7190 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }), |
| 7191 | registerAlias(src_reg, abi_size), |
| 7192 | ); |
| 7141 | 7193 | } |
| 7142 | 7194 | } |
| 7143 | 7195 | |
| ... | ... | @@ -7170,9 +7222,15 @@ fn genInlineMemcpy( |
| 7170 | 7222 | switch (dst_ptr) { |
| 7171 | 7223 | .memory, .linker_load => { |
| 7172 | 7224 | try self.loadMemPtrIntoRegister(.rdi, Type.usize, dst_ptr); |
| 7225 | // Load the pointer, which is stored in memory |
| 7226 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); |
| 7173 | 7227 | }, |
| 7174 | | .ptr_stack_offset, .stack_offset => |off| { |
| 7175 | | try self.asmRegisterMemory(.lea, .rdi, Memory.sib(.qword, .{ |
| 7228 | .stack_offset, .ptr_stack_offset => |off| { |
| 7229 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7230 | .stack_offset => .mov, |
| 7231 | .ptr_stack_offset => .lea, |
| 7232 | else => unreachable, |
| 7233 | }, .rdi, Memory.sib(.qword, .{ |
| 7176 | 7234 | .base = opts.dest_stack_base orelse .rbp, |
| 7177 | 7235 | .disp = -off, |
| 7178 | 7236 | })); |
| ... | ... | @@ -7192,9 +7250,15 @@ fn genInlineMemcpy( |
| 7192 | 7250 | switch (src_ptr) { |
| 7193 | 7251 | .memory, .linker_load => { |
| 7194 | 7252 | try self.loadMemPtrIntoRegister(.rsi, Type.usize, src_ptr); |
| 7253 | // Load the pointer, which is stored in memory |
| 7254 | try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi })); |
| 7195 | 7255 | }, |
| 7196 | | .ptr_stack_offset, .stack_offset => |off| { |
| 7197 | | try self.asmRegisterMemory(.lea, .rsi, Memory.sib(.qword, .{ |
| 7256 | .stack_offset, .ptr_stack_offset => |off| { |
| 7257 | try self.asmRegisterMemory(switch (src_ptr) { |
| 7258 | .stack_offset => .mov, |
| 7259 | .ptr_stack_offset => .lea, |
| 7260 | else => unreachable, |
| 7261 | }, .rsi, Memory.sib(.qword, .{ |
| 7198 | 7262 | .base = opts.source_stack_base orelse .rbp, |
| 7199 | 7263 | .disp = -off, |
| 7200 | 7264 | })); |
| ... | ... | @@ -7237,9 +7301,15 @@ fn genInlineMemset( |
| 7237 | 7301 | switch (dst_ptr) { |
| 7238 | 7302 | .memory, .linker_load => { |
| 7239 | 7303 | try self.loadMemPtrIntoRegister(.rdi, Type.usize, dst_ptr); |
| 7304 | // Load the pointer, which is stored in memory |
| 7305 | try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi })); |
| 7240 | 7306 | }, |
| 7241 | | .ptr_stack_offset, .stack_offset => |off| { |
| 7242 | | try self.asmRegisterMemory(.lea, .rdi, Memory.sib(.qword, .{ |
| 7307 | .stack_offset, .ptr_stack_offset => |off| { |
| 7308 | try self.asmRegisterMemory(switch (dst_ptr) { |
| 7309 | .stack_offset => .mov, |
| 7310 | .ptr_stack_offset => .lea, |
| 7311 | else => unreachable, |
| 7312 | }, .rdi, Memory.sib(.qword, .{ |
| 7243 | 7313 | .base = opts.dest_stack_base orelse .rbp, |
| 7244 | 7314 | .disp = -off, |
| 7245 | 7315 | })); |
| ... | ... | @@ -7979,7 +8049,6 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 7979 | 8049 | }; |
| 7980 | 8050 | defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 7981 | 8051 | |
| 7982 | | const src_ty = self.air.typeOf(extra.lhs); |
| 7983 | 8052 | const src_ptr = try self.resolveInst(extra.lhs); |
| 7984 | 8053 | const src_ptr_lock: ?RegisterLock = switch (src_ptr) { |
| 7985 | 8054 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| ... | ... | @@ -7994,25 +8063,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 7994 | 8063 | }; |
| 7995 | 8064 | defer if (len_lock) |lock| self.register_manager.unlockReg(lock); |
| 7996 | 8065 | |
| 7997 | | // TODO Is this the only condition for pointer dereference for memcpy? |
| 7998 | | const src: MCValue = blk: { |
| 7999 | | switch (src_ptr) { |
| 8000 | | .linker_load, .memory => { |
| 8001 | | const reg = try self.register_manager.allocReg(null, gp); |
| 8002 | | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 8003 | | try self.asmRegisterMemory(.mov, reg, Memory.sib(.qword, .{ .base = reg })); |
| 8004 | | break :blk MCValue{ .register = reg }; |
| 8005 | | }, |
| 8006 | | else => break :blk src_ptr, |
| 8007 | | } |
| 8008 | | }; |
| 8009 | | const src_lock: ?RegisterLock = switch (src) { |
| 8010 | | .register => |reg| self.register_manager.lockReg(reg), |
| 8011 | | else => null, |
| 8012 | | }; |
| 8013 | | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 8014 | | |
| 8015 | | try self.genInlineMemcpy(dst_ptr, src, len, .{}); |
| 8066 | try self.genInlineMemcpy(dst_ptr, src_ptr, len, .{}); |
| 8016 | 8067 | |
| 8017 | 8068 | return self.finishAir(inst, .none, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 8018 | 8069 | } |
| ... | ... | @@ -8156,11 +8207,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8156 | 8207 | switch (result_ty.zigTypeTag()) { |
| 8157 | 8208 | .Struct => { |
| 8158 | 8209 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |
| 8159 | | const dst_mcv = MCValue{ .stack_offset = stack_offset }; |
| 8160 | 8210 | if (result_ty.containerLayout() == .Packed) { |
| 8161 | 8211 | const struct_obj = result_ty.castTag(.@"struct").?.data; |
| 8162 | 8212 | try self.genInlineMemset( |
| 8163 | | dst_mcv, |
| 8213 | .{ .ptr_stack_offset = stack_offset }, |
| 8164 | 8214 | .{ .immediate = 0 }, |
| 8165 | 8215 | .{ .immediate = abi_size }, |
| 8166 | 8216 | .{}, |
| ... | ... | @@ -8236,7 +8286,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 8236 | 8286 | const elem_mcv = try self.resolveInst(elem); |
| 8237 | 8287 | try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); |
| 8238 | 8288 | } |
| 8239 | | break :res dst_mcv; |
| 8289 | break :res .{ .stack_offset = stack_offset }; |
| 8240 | 8290 | }, |
| 8241 | 8291 | .Array => { |
| 8242 | 8292 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |