| ... | ... | @@ -3669,52 +3669,67 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3669 | 3669 | .none => unreachable, |
| 3670 | 3670 | .dead => unreachable, |
| 3671 | 3671 | .unreach => unreachable, |
| 3672 | | .eflags => |cc| { |
| 3673 | | try self.asmSetccMemory(Memory.sib( |
| 3674 | | Memory.PtrSize.fromSize(abi_size), |
| 3675 | | .{ .base = reg.to64() }, |
| 3676 | | ), cc); |
| 3677 | | }, |
| 3678 | | .undef => { |
| 3679 | | if (!self.wantSafety()) return; // The already existing value will do just fine. |
| 3680 | | switch (abi_size) { |
| 3681 | | 1 => try self.store(ptr, .{ .immediate = 0xaa }, ptr_ty, value_ty), |
| 3682 | | 2 => try self.store(ptr, .{ .immediate = 0xaaaa }, ptr_ty, value_ty), |
| 3683 | | 4 => try self.store(ptr, .{ .immediate = 0xaaaaaaaa }, ptr_ty, value_ty), |
| 3684 | | 8 => try self.store(ptr, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, ptr_ty, value_ty), |
| 3685 | | else => try self.genInlineMemset(ptr, .{ .immediate = 0xaa }, .{ .immediate = abi_size }, .{}), |
| 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 | | } |
| 3672 | .eflags => |cc| try self.asmSetccMemory( |
| 3673 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }), |
| 3674 | cc, |
| 3675 | ), |
| 3676 | .undef => if (self.wantSafety()) switch (abi_size) { |
| 3677 | 1 => try self.store(ptr, .{ .immediate = 0xaa }, ptr_ty, value_ty), |
| 3678 | 2 => try self.store(ptr, .{ .immediate = 0xaaaa }, ptr_ty, value_ty), |
| 3679 | 4 => try self.store(ptr, .{ .immediate = 0xaaaaaaaa }, ptr_ty, value_ty), |
| 3680 | 8 => try self.store(ptr, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, ptr_ty, value_ty), |
| 3681 | else => try self.genInlineMemset( |
| 3682 | ptr, |
| 3683 | .{ .immediate = 0xaa }, |
| 3684 | .{ .immediate = abi_size }, |
| 3685 | .{}, |
| 3686 | ), |
| 3714 | 3687 | }, |
| 3715 | | .register => |src_reg| { |
| 3716 | | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); |
| 3688 | .immediate => |imm| switch (self.regBitSize(value_ty)) { |
| 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 | 3733 | .register_overflow => |ro| { |
| 3719 | 3734 | const ro_reg_lock = self.register_manager.lockReg(ro.reg); |
| 3720 | 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 | 3780 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 3766 | 3781 | |
| 3767 | 3782 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); |
| 3768 | | |
| 3769 | | // To get the actual address of the value we want to modify we have to go through the GOT |
| 3783 | // Load the pointer, which is stored in memory |
| 3770 | 3784 | try self.asmRegisterMemory( |
| 3771 | 3785 | .mov, |
| 3772 | 3786 | addr_reg.to64(), |
| ... | ... | @@ -3774,62 +3788,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3774 | 3788 | ); |
| 3775 | 3789 | |
| 3776 | 3790 | const new_ptr = MCValue{ .register = addr_reg.to64() }; |
| 3777 | | |
| 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 | | } |
| 3791 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| 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 | 4846 | registerAlias(src_reg, abi_size), |
| 4888 | 4847 | ), |
| 4889 | 4848 | }, |
| 4890 | | .immediate => |imm| { |
| 4891 | | switch (self.regBitSize(ty)) { |
| 4892 | | 8 => try self.asmRegisterImmediate( |
| 4893 | | mir_tag, |
| 4894 | | dst_alias, |
| 4895 | | if (math.cast(i8, @bitCast(i64, imm))) |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)) |
| 4849 | .immediate => |imm| switch (self.regBitSize(ty)) { |
| 4850 | 8 => try self.asmRegisterImmediate( |
| 4851 | mir_tag, |
| 4852 | dst_alias, |
| 4853 | if (math.cast(i8, @bitCast(i64, imm))) |small| |
| 4854 | Immediate.s(small) |
| 4918 | 4855 | else |
| 4919 | | try self.asmRegisterRegister(mir_tag, dst_alias, registerAlias( |
| 4920 | | try self.copyToTmpRegister(ty, src_mcv), |
| 4921 | | abi_size, |
| 4922 | | )), |
| 4923 | | else => unreachable, |
| 4924 | | } |
| 4856 | Immediate.u(@intCast(u8, imm)), |
| 4857 | ), |
| 4858 | 16 => try self.asmRegisterImmediate( |
| 4859 | mir_tag, |
| 4860 | dst_alias, |
| 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 | 4883 | .memory, .linker_load, .eflags => { |
| 4927 | 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 | 4888 | const reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4932 | 4889 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); |
| 4933 | 4890 | }, |
| 4934 | | .stack_offset => |off| { |
| 4935 | | try self.asmRegisterMemory( |
| 4936 | | mir_tag, |
| 4937 | | registerAlias(dst_reg, abi_size), |
| 4938 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 4939 | | ); |
| 4940 | | }, |
| 4891 | .stack_offset => |off| try self.asmRegisterMemory( |
| 4892 | mir_tag, |
| 4893 | registerAlias(dst_reg, abi_size), |
| 4894 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 4895 | ), |
| 4941 | 4896 | } |
| 4942 | 4897 | }, |
| 4943 | 4898 | .memory, .linker_load, .stack_offset => { |