| ... | @@ -3669,52 +3669,67 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3669,52 +3669,67 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3669 | .none => unreachable, | 3669 | .none => unreachable, |
| 3670 | .dead => unreachable, | 3670 | .dead => unreachable, |
| 3671 | .unreach => unreachable, | 3671 | .unreach => unreachable, |
| 3672 | .eflags => |cc| { | 3672 | .eflags => |cc| try self.asmSetccMemory( |
| 3673 | try self.asmSetccMemory(Memory.sib( | 3673 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| 3674 | Memory.PtrSize.fromSize(abi_size), | 3674 | cc, |
| 3675 | .{ .base = reg.to64() }, | 3675 | ), |
| 3676 | ), cc); | 3676 | .undef => if (self.wantSafety()) switch (abi_size) { |
| 3677 | }, | 3677 | 1 => try self.store(ptr, .{ .immediate = 0xaa }, ptr_ty, value_ty), |
| 3678 | .undef => { | 3678 | 2 => try self.store(ptr, .{ .immediate = 0xaaaa }, ptr_ty, value_ty), |
| 3679 | if (!self.wantSafety()) return; // The already existing value will do just fine. | 3679 | 4 => try self.store(ptr, .{ .immediate = 0xaaaaaaaa }, ptr_ty, value_ty), |
| 3680 | switch (abi_size) { | 3680 | 8 => try self.store(ptr, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, ptr_ty, value_ty), |
| 3681 | 1 => try self.store(ptr, .{ .immediate = 0xaa }, ptr_ty, value_ty), | 3681 | else => try self.genInlineMemset( |
| 3682 | 2 => try self.store(ptr, .{ .immediate = 0xaaaa }, ptr_ty, value_ty), | 3682 | ptr, |
| 3683 | 4 => try self.store(ptr, .{ .immediate = 0xaaaaaaaa }, ptr_ty, value_ty), | 3683 | .{ .immediate = 0xaa }, |
| 3684 | 8 => try self.store(ptr, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, ptr_ty, value_ty), | 3684 | .{ .immediate = abi_size }, |
| 3685 | else => try self.genInlineMemset(ptr, .{ .immediate = 0xaa }, .{ .immediate = abi_size }, .{}), | 3685 | .{}, |
| 3686 | } | 3686 | ), |
| 3687 | }, | | |
| 3688 | .immediate => |imm| { | | |
| 3689 | switch (abi_size) { | | |
| 3690 | 1, 2, 4 => { | | |
| 3691 | const immediate = if (value_ty.isSignedInt()) | | |
| 3692 | Immediate.s(@intCast(i32, @bitCast(i64, imm))) | | |
| 3693 | else | | |
| 3694 | Immediate.u(@truncate(u32, imm)); | | |
| 3695 | try self.asmMemoryImmediate(.mov, Memory.sib( | | |
| 3696 | Memory.PtrSize.fromSize(abi_size), | | |
| 3697 | .{ .base = reg.to64() }, | | |
| 3698 | ), immediate); | | |
| 3699 | }, | | |
| 3700 | 8 => { | | |
| 3701 | // TODO: optimization: if the imm is only using the lower | | |
| 3702 | // 4 bytes and can be sign extended we can use a normal mov | | |
| 3703 | // with indirect addressing (mov [reg64], imm32). | | |
| 3704 | | | |
| 3705 | // movabs does not support indirect register addressing | | |
| 3706 | // so we need an extra register and an extra mov. | | |
| 3707 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); | | |
| 3708 | return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | | |
| 3709 | }, | | |
| 3710 | else => { | | |
| 3711 | return self.fail("TODO implement set pointee with immediate of ABI size {d}", .{abi_size}); | | |
| 3712 | }, | | |
| 3713 | } | | |
| 3714 | }, | 3687 | }, |
| 3715 | .register => |src_reg| { | 3688 | .immediate => |imm| switch (self.regBitSize(value_ty)) { |
| 3716 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); | 3689 | 8 => try self.asmMemoryImmediate( |
| | 3690 | .mov, |
| | 3691 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| | 3692 | if (math.cast(i8, @bitCast(i64, imm))) |small| |
| | 3693 | Immediate.s(small) |
| | 3694 | else |
| | 3695 | Immediate.u(@intCast(u8, imm)), |
| | 3696 | ), |
| | 3697 | 16 => try self.asmMemoryImmediate( |
| | 3698 | .mov, |
| | 3699 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| | 3700 | if (math.cast(i16, @bitCast(i64, imm))) |small| |
| | 3701 | Immediate.s(small) |
| | 3702 | else |
| | 3703 | Immediate.u(@intCast(u16, imm)), |
| | 3704 | ), |
| | 3705 | 32 => try self.asmMemoryImmediate( |
| | 3706 | .mov, |
| | 3707 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| | 3708 | if (math.cast(i32, @bitCast(i64, imm))) |small| |
| | 3709 | Immediate.s(small) |
| | 3710 | else |
| | 3711 | Immediate.u(@intCast(u32, imm)), |
| | 3712 | ), |
| | 3713 | 64 => if (math.cast(i32, @bitCast(i64, imm))) |small| |
| | 3714 | try self.asmMemoryImmediate( |
| | 3715 | .mov, |
| | 3716 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| | 3717 | Immediate.s(small), |
| | 3718 | ) |
| | 3719 | else |
| | 3720 | try self.asmMemoryRegister( |
| | 3721 | .mov, |
| | 3722 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| | 3723 | registerAlias(try self.copyToTmpRegister(value_ty, value), abi_size), |
| | 3724 | ), |
| | 3725 | else => unreachable, |
| 3717 | }, | 3726 | }, |
| | 3727 | .register => |src_reg| try self.genInlineMemcpyRegisterRegister( |
| | 3728 | value_ty, |
| | 3729 | reg, |
| | 3730 | src_reg, |
| | 3731 | 0, |
| | 3732 | ), |
| 3718 | .register_overflow => |ro| { | 3733 | .register_overflow => |ro| { |
| 3719 | const ro_reg_lock = self.register_manager.lockReg(ro.reg); | 3734 | const ro_reg_lock = self.register_manager.lockReg(ro.reg); |
| 3720 | defer if (ro_reg_lock) |lock| self.register_manager.unlockReg(lock); | 3735 | defer if (ro_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | @@ -3765,8 +3780,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3765,8 +3780,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3765 | defer self.register_manager.unlockReg(addr_reg_lock); | 3780 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3766 | | 3781 | |
| 3767 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); | 3782 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); |
| 3768 | | 3783 | // Load the pointer, which is stored in memory |
| 3769 | // To get the actual address of the value we want to modify we have to go through the GOT | | |
| 3770 | try self.asmRegisterMemory( | 3784 | try self.asmRegisterMemory( |
| 3771 | .mov, | 3785 | .mov, |
| 3772 | addr_reg.to64(), | 3786 | addr_reg.to64(), |
| ... | @@ -3774,62 +3788,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3774,62 +3788,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3774 | ); | 3788 | ); |
| 3775 | | 3789 | |
| 3776 | const new_ptr = MCValue{ .register = addr_reg.to64() }; | 3790 | const new_ptr = MCValue{ .register = addr_reg.to64() }; |
| 3777 | | 3791 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| 3778 | switch (value) { | | |
| 3779 | .immediate => |imm| { | | |
| 3780 | if (abi_size > 8) { | | |
| 3781 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); | | |
| 3782 | } | | |
| 3783 | | | |
| 3784 | if (abi_size == 8) { | | |
| 3785 | // TODO | | |
| 3786 | const top_bits: u32 = @intCast(u32, imm >> 32); | | |
| 3787 | const can_extend = if (value_ty.isUnsignedInt()) | | |
| 3788 | (top_bits == 0) and (imm & 0x8000_0000) == 0 | | |
| 3789 | else | | |
| 3790 | top_bits == 0xffff_ffff; | | |
| 3791 | | | |
| 3792 | if (!can_extend) { | | |
| 3793 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); | | |
| 3794 | } | | |
| 3795 | } | | |
| 3796 | try self.asmMemoryImmediate( | | |
| 3797 | .mov, | | |
| 3798 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg.to64() }), | | |
| 3799 | Immediate.u(@intCast(u32, imm)), | | |
| 3800 | ); | | |
| 3801 | }, | | |
| 3802 | .register => { | | |
| 3803 | return self.store(new_ptr, value, ptr_ty, value_ty); | | |
| 3804 | }, | | |
| 3805 | .linker_load, .memory => { | | |
| 3806 | if (abi_size <= 8) { | | |
| 3807 | const tmp_reg = try self.register_manager.allocReg(null, gp); | | |
| 3808 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | | |
| 3809 | defer self.register_manager.unlockReg(tmp_reg_lock); | | |
| 3810 | | | |
| 3811 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); | | |
| 3812 | try self.asmRegisterMemory( | | |
| 3813 | .mov, | | |
| 3814 | tmp_reg, | | |
| 3815 | Memory.sib(.qword, .{ .base = tmp_reg }), | | |
| 3816 | ); | | |
| 3817 | | | |
| 3818 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | | |
| 3819 | } | | |
| 3820 | | | |
| 3821 | try self.genInlineMemcpy(new_ptr, value, .{ .immediate = abi_size }, .{}); | | |
| 3822 | }, | | |
| 3823 | .stack_offset => { | | |
| 3824 | if (abi_size <= 8) { | | |
| 3825 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); | | |
| 3826 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | | |
| 3827 | } | | |
| 3828 | | | |
| 3829 | try self.genInlineMemcpy(new_ptr, value, .{ .immediate = abi_size }, .{}); | | |
| 3830 | }, | | |
| 3831 | else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}), | | |
| 3832 | } | | |
| 3833 | }, | 3792 | }, |
| 3834 | } | 3793 | } |
| 3835 | } | 3794 | } |
| ... | @@ -4887,41 +4846,39 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -4887,41 +4846,39 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4887 | registerAlias(src_reg, abi_size), | 4846 | registerAlias(src_reg, abi_size), |
| 4888 | ), | 4847 | ), |
| 4889 | }, | 4848 | }, |
| 4890 | .immediate => |imm| { | 4849 | .immediate => |imm| switch (self.regBitSize(ty)) { |
| 4891 | switch (self.regBitSize(ty)) { | 4850 | 8 => try self.asmRegisterImmediate( |
| 4892 | 8 => try self.asmRegisterImmediate( | 4851 | mir_tag, |
| 4893 | mir_tag, | 4852 | dst_alias, |
| 4894 | dst_alias, | 4853 | if (math.cast(i8, @bitCast(i64, imm))) |small| |
| 4895 | if (math.cast(i8, @bitCast(i64, imm))) |small| | 4854 | Immediate.s(small) |
| 4896 | Immediate.s(small) | | |
| 4897 | else | | |
| 4898 | Immediate.u(@intCast(u8, imm)), | | |
| 4899 | ), | | |
| 4900 | 16 => try self.asmRegisterImmediate( | | |
| 4901 | mir_tag, | | |
| 4902 | dst_alias, | | |
| 4903 | if (math.cast(i16, @bitCast(i64, imm))) |small| | | |
| 4904 | Immediate.s(small) | | |
| 4905 | else | | |
| 4906 | Immediate.u(@intCast(u16, imm)), | | |
| 4907 | ), | | |
| 4908 | 32 => try self.asmRegisterImmediate( | | |
| 4909 | mir_tag, | | |
| 4910 | dst_alias, | | |
| 4911 | if (math.cast(i32, @bitCast(i64, imm))) |small| | | |
| 4912 | Immediate.s(small) | | |
| 4913 | else | | |
| 4914 | Immediate.u(@intCast(u32, imm)), | | |
| 4915 | ), | | |
| 4916 | 64 => if (math.cast(i32, @bitCast(i64, imm))) |small| | | |
| 4917 | try self.asmRegisterImmediate(mir_tag, dst_alias, Immediate.s(small)) | | |
| 4918 | else | 4855 | else |
| 4919 | try self.asmRegisterRegister(mir_tag, dst_alias, registerAlias( | 4856 | Immediate.u(@intCast(u8, imm)), |
| 4920 | try self.copyToTmpRegister(ty, src_mcv), | 4857 | ), |
| 4921 | abi_size, | 4858 | 16 => try self.asmRegisterImmediate( |
| 4922 | )), | 4859 | mir_tag, |
| 4923 | else => unreachable, | 4860 | dst_alias, |
| 4924 | } | 4861 | if (math.cast(i16, @bitCast(i64, imm))) |small| |
| | 4862 | Immediate.s(small) |
| | 4863 | else |
| | 4864 | Immediate.u(@intCast(u16, imm)), |
| | 4865 | ), |
| | 4866 | 32 => try self.asmRegisterImmediate( |
| | 4867 | mir_tag, |
| | 4868 | dst_alias, |
| | 4869 | if (math.cast(i32, @bitCast(i64, imm))) |small| |
| | 4870 | Immediate.s(small) |
| | 4871 | else |
| | 4872 | Immediate.u(@intCast(u32, imm)), |
| | 4873 | ), |
| | 4874 | 64 => if (math.cast(i32, @bitCast(i64, imm))) |small| |
| | 4875 | try self.asmRegisterImmediate(mir_tag, dst_alias, Immediate.s(small)) |
| | 4876 | else |
| | 4877 | try self.asmRegisterRegister(mir_tag, dst_alias, registerAlias( |
| | 4878 | try self.copyToTmpRegister(ty, src_mcv), |
| | 4879 | abi_size, |
| | 4880 | )), |
| | 4881 | else => unreachable, |
| 4925 | }, | 4882 | }, |
| 4926 | .memory, .linker_load, .eflags => { | 4883 | .memory, .linker_load, .eflags => { |
| 4927 | assert(abi_size <= 8); | 4884 | assert(abi_size <= 8); |
| ... | @@ -4931,13 +4888,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -4931,13 +4888,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4931 | const reg = try self.copyToTmpRegister(ty, src_mcv); | 4888 | const reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4932 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); | 4889 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); |
| 4933 | }, | 4890 | }, |
| 4934 | .stack_offset => |off| { | 4891 | .stack_offset => |off| try self.asmRegisterMemory( |
| 4935 | try self.asmRegisterMemory( | 4892 | mir_tag, |
| 4936 | mir_tag, | 4893 | registerAlias(dst_reg, abi_size), |
| 4937 | registerAlias(dst_reg, abi_size), | 4894 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 4938 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), | 4895 | ), |
| 4939 | ); | | |
| 4940 | }, | | |
| 4941 | } | 4896 | } |
| 4942 | }, | 4897 | }, |
| 4943 | .memory, .linker_load, .stack_offset => { | 4898 | .memory, .linker_load, .stack_offset => { |