| ... | ... | @@ -4010,9 +4010,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue |
| 4010 | 4010 | .register_overflow => unreachable, |
| 4011 | 4011 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 4012 | 4012 | .ptr_stack_offset, .stack_offset => |off| { |
| 4013 | | if (off > math.maxInt(i32)) { |
| 4014 | | return self.fail("stack offset too large", .{}); |
| 4015 | | } |
| 4016 | 4013 | if (abi_size > 8) { |
| 4017 | 4014 | return self.fail("TODO implement {} for stack dst with large ABI", .{mir_tag}); |
| 4018 | 4015 | } |
| ... | ... | @@ -4454,9 +4451,6 @@ fn genBinOp( |
| 4454 | 4451 | if (lhs_ty.zigTypeTag() == .Vector) { |
| 4455 | 4452 | return self.fail("TODO implement genBinOp for {}", .{lhs_ty.fmt(self.bin_file.options.module.?)}); |
| 4456 | 4453 | } |
| 4457 | | if (lhs_ty.abiSize(self.target.*) > 8) { |
| 4458 | | return self.fail("TODO implement genBinOp for {}", .{lhs_ty.fmt(self.bin_file.options.module.?)}); |
| 4459 | | } |
| 4460 | 4454 | |
| 4461 | 4455 | switch (lhs) { |
| 4462 | 4456 | .immediate => |imm| switch (imm) { |
| ... | ... | @@ -4686,7 +4680,6 @@ fn genBinOp( |
| 4686 | 4680 | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 4687 | 4681 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 4688 | 4682 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 4689 | | |
| 4690 | 4683 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, mat_src_mcv); |
| 4691 | 4684 | |
| 4692 | 4685 | // To get the actual address of the value we want to modify we |
| ... | ... | @@ -4801,9 +4794,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4801 | 4794 | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = reg }); |
| 4802 | 4795 | }, |
| 4803 | 4796 | .stack_offset => |off| { |
| 4804 | | if (off > math.maxInt(i32)) { |
| 4805 | | return self.fail("stack offset too large", .{}); |
| 4806 | | } |
| 4807 | 4797 | try self.asmRegisterMemory( |
| 4808 | 4798 | mir_tag, |
| 4809 | 4799 | registerAlias(dst_reg, abi_size), |
| ... | ... | @@ -4812,78 +4802,155 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 4812 | 4802 | }, |
| 4813 | 4803 | } |
| 4814 | 4804 | }, |
| 4815 | | .ptr_stack_offset, .stack_offset => |off| { |
| 4816 | | if (off > math.maxInt(i32)) { |
| 4817 | | return self.fail("stack offset too large", .{}); |
| 4818 | | } |
| 4819 | | if (abi_size > 8) { |
| 4820 | | return self.fail("TODO implement {} for stack dst with large ABI", .{mir_tag}); |
| 4821 | | } |
| 4805 | .ptr_stack_offset, .stack_offset => |dst_off| { |
| 4806 | const src: ?struct { |
| 4807 | limb_reg: Register, |
| 4808 | limb_lock: RegisterLock, |
| 4809 | addr_reg: Register, |
| 4810 | addr_lock: RegisterLock, |
| 4811 | } = switch (src_mcv) { |
| 4812 | else => null, |
| 4813 | .memory, .linker_load => addr: { |
| 4814 | const src_limb_reg = try self.register_manager.allocReg(null, gp); |
| 4815 | const src_limb_lock = self.register_manager.lockRegAssumeUnused(src_limb_reg); |
| 4816 | errdefer self.register_manager.unlockReg(src_limb_lock); |
| 4817 | |
| 4818 | const src_addr_reg = try self.register_manager.allocReg(null, gp); |
| 4819 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 4820 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 4821 | |
| 4822 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_mcv); |
| 4823 | // To get the actual address of the value we want to modify we |
| 4824 | // we have to go through the GOT |
| 4825 | try self.asmRegisterMemory( |
| 4826 | .mov, |
| 4827 | src_addr_reg, |
| 4828 | Memory.sib(.qword, .{ .base = src_addr_reg }), |
| 4829 | ); |
| 4822 | 4830 | |
| 4823 | | switch (src_mcv) { |
| 4824 | | .none => unreachable, |
| 4825 | | .undef => unreachable, |
| 4826 | | .dead, .unreach => unreachable, |
| 4827 | | .register_overflow => unreachable, |
| 4828 | | .register => |src_reg| { |
| 4829 | | try self.asmMemoryRegister(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4830 | | .base = .rbp, |
| 4831 | | .disp = -off, |
| 4832 | | }), registerAlias(src_reg, abi_size)); |
| 4831 | break :addr .{ |
| 4832 | .addr_reg = src_addr_reg, |
| 4833 | .addr_lock = src_addr_lock, |
| 4834 | .limb_reg = src_limb_reg, |
| 4835 | .limb_lock = src_limb_lock, |
| 4836 | }; |
| 4833 | 4837 | }, |
| 4834 | | .immediate => |imm| { |
| 4835 | | switch (self.regBitSize(ty)) { |
| 4836 | | 8, 16, 32 => { |
| 4837 | | try self.asmMemoryImmediate( |
| 4838 | | mir_tag, |
| 4839 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4840 | | .base = .rbp, |
| 4841 | | .disp = -off, |
| 4842 | | }), |
| 4843 | | if (math.cast(i32, @bitCast(i64, imm))) |small| |
| 4844 | | Immediate.s(small) |
| 4845 | | else |
| 4846 | | Immediate.u(@intCast(u32, imm)), |
| 4847 | | ); |
| 4848 | | }, |
| 4849 | | 64 => { |
| 4850 | | if (math.cast(i32, @bitCast(i64, imm))) |small| { |
| 4838 | }; |
| 4839 | defer if (src) |locks| { |
| 4840 | self.register_manager.unlockReg(locks.limb_lock); |
| 4841 | self.register_manager.unlockReg(locks.addr_lock); |
| 4842 | }; |
| 4843 | |
| 4844 | const ty_signedness = |
| 4845 | if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned; |
| 4846 | const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) { |
| 4847 | .signed => Type.usize, |
| 4848 | .unsigned => Type.isize, |
| 4849 | }; |
| 4850 | const limb_abi_size = @min(abi_size, 8); |
| 4851 | var off: i32 = 0; |
| 4852 | while (off < abi_size) : (off += 8) { |
| 4853 | const mir_limb_tag = switch (off) { |
| 4854 | 0 => mir_tag, |
| 4855 | else => switch (mir_tag) { |
| 4856 | .add => .adc, |
| 4857 | .sub => .sbb, |
| 4858 | .@"or", .@"and", .xor => mir_tag, |
| 4859 | else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{ |
| 4860 | @tagName(mir_tag), |
| 4861 | }), |
| 4862 | }, |
| 4863 | }; |
| 4864 | const dst_limb_mem = Memory.sib( |
| 4865 | Memory.PtrSize.fromSize(limb_abi_size), |
| 4866 | .{ .base = .rbp, .disp = off - dst_off }, |
| 4867 | ); |
| 4868 | switch (src_mcv) { |
| 4869 | .none => unreachable, |
| 4870 | .undef => unreachable, |
| 4871 | .dead, .unreach => unreachable, |
| 4872 | .register_overflow => unreachable, |
| 4873 | .register => |src_reg| { |
| 4874 | assert(off == 0); |
| 4875 | try self.asmMemoryRegister( |
| 4876 | mir_limb_tag, |
| 4877 | dst_limb_mem, |
| 4878 | registerAlias(src_reg, limb_abi_size), |
| 4879 | ); |
| 4880 | }, |
| 4881 | .immediate => |src_imm| { |
| 4882 | const imm = if (off == 0) src_imm else switch (ty_signedness) { |
| 4883 | .signed => @bitCast(u64, @bitCast(i64, src_imm) >> 63), |
| 4884 | .unsigned => 0, |
| 4885 | }; |
| 4886 | switch (self.regBitSize(limb_ty)) { |
| 4887 | 8, 16, 32 => { |
| 4851 | 4888 | try self.asmMemoryImmediate( |
| 4852 | | mir_tag, |
| 4853 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4854 | | .base = .rbp, |
| 4855 | | .disp = -off, |
| 4856 | | }), |
| 4857 | | Immediate.s(small), |
| 4889 | mir_limb_tag, |
| 4890 | dst_limb_mem, |
| 4891 | if (math.cast(i32, @bitCast(i64, imm))) |small| |
| 4892 | Immediate.s(small) |
| 4893 | else |
| 4894 | Immediate.u(@intCast(u32, imm)), |
| 4858 | 4895 | ); |
| 4859 | | } else { |
| 4860 | | try self.asmMemoryRegister( |
| 4861 | | mir_tag, |
| 4862 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4863 | | .base = .rbp, |
| 4864 | | .disp = -off, |
| 4865 | | }), |
| 4866 | | registerAlias(try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| 4867 | | ); |
| 4868 | | } |
| 4869 | | }, |
| 4870 | | else => return self.fail("TODO genBinOpMir implement large immediate ABI", .{}), |
| 4871 | | } |
| 4872 | | }, |
| 4873 | | .memory, |
| 4874 | | .linker_load, |
| 4875 | | .stack_offset, |
| 4876 | | .ptr_stack_offset, |
| 4877 | | .eflags, |
| 4878 | | => { |
| 4879 | | assert(abi_size <= 8); |
| 4880 | | |
| 4881 | | const tmp_reg = try self.copyToTmpRegister(ty, src_mcv); |
| 4882 | | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| 4883 | | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| 4896 | }, |
| 4897 | 64 => { |
| 4898 | if (math.cast(i32, @bitCast(i64, imm))) |small| { |
| 4899 | try self.asmMemoryImmediate( |
| 4900 | mir_limb_tag, |
| 4901 | dst_limb_mem, |
| 4902 | Immediate.s(small), |
| 4903 | ); |
| 4904 | } else { |
| 4905 | try self.asmMemoryRegister( |
| 4906 | mir_limb_tag, |
| 4907 | dst_limb_mem, |
| 4908 | registerAlias( |
| 4909 | try self.copyToTmpRegister(limb_ty, .{ .immediate = imm }), |
| 4910 | limb_abi_size, |
| 4911 | ), |
| 4912 | ); |
| 4913 | } |
| 4914 | }, |
| 4915 | else => unreachable, |
| 4916 | } |
| 4917 | }, |
| 4918 | .memory, .linker_load => { |
| 4919 | try self.asmRegisterMemory( |
| 4920 | .mov, |
| 4921 | registerAlias(src.?.limb_reg, limb_abi_size), |
| 4922 | Memory.sib( |
| 4923 | Memory.PtrSize.fromSize(limb_abi_size), |
| 4924 | .{ .base = src.?.addr_reg, .disp = off }, |
| 4925 | ), |
| 4926 | ); |
| 4927 | try self.asmMemoryRegister( |
| 4928 | mir_limb_tag, |
| 4929 | dst_limb_mem, |
| 4930 | registerAlias(src.?.limb_reg, limb_abi_size), |
| 4931 | ); |
| 4932 | }, |
| 4933 | .stack_offset, .ptr_stack_offset, .eflags => { |
| 4934 | const src_limb_reg = try self.copyToTmpRegister(limb_ty, switch (src_mcv) { |
| 4935 | .stack_offset => |src_off| .{ .stack_offset = src_off - off }, |
| 4936 | .ptr_stack_offset, |
| 4937 | .eflags, |
| 4938 | => off: { |
| 4939 | assert(off == 0); |
| 4940 | break :off src_mcv; |
| 4941 | }, |
| 4942 | else => unreachable, |
| 4943 | }); |
| 4944 | const src_limb_lock = self.register_manager.lockReg(src_limb_reg); |
| 4945 | defer if (src_limb_lock) |lock| self.register_manager.unlockReg(lock); |
| 4884 | 4946 | |
| 4885 | | return self.genBinOpMir(mir_tag, ty, dst_mcv, .{ .register = tmp_reg }); |
| 4886 | | }, |
| 4947 | try self.asmMemoryRegister( |
| 4948 | mir_limb_tag, |
| 4949 | dst_limb_mem, |
| 4950 | registerAlias(src_limb_reg, limb_abi_size), |
| 4951 | ); |
| 4952 | }, |
| 4953 | } |
| 4887 | 4954 | } |
| 4888 | 4955 | }, |
| 4889 | 4956 | .memory => { |
| ... | ... | @@ -6735,10 +6802,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 6735 | 6802 | } |
| 6736 | 6803 | }, |
| 6737 | 6804 | .register => |reg| { |
| 6738 | | if (stack_offset > math.maxInt(i32)) { |
| 6739 | | return self.fail("stack offset too large", .{}); |
| 6740 | | } |
| 6741 | | |
| 6742 | 6805 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 6743 | 6806 | |
| 6744 | 6807 | switch (ty.zigTypeTag()) { |
| ... | ... | @@ -6973,13 +7036,11 @@ fn genInlineMemset( |
| 6973 | 7036 | |
| 6974 | 7037 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 6975 | 7038 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 7039 | if (abi_size > 8) return self.fail("genSetReg called with a value larger than one register", .{}); |
| 6976 | 7040 | switch (mcv) { |
| 6977 | 7041 | .dead => unreachable, |
| 6978 | 7042 | .register_overflow => unreachable, |
| 6979 | 7043 | .ptr_stack_offset => |off| { |
| 6980 | | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 6981 | | return self.fail("stack offset too large", .{}); |
| 6982 | | } |
| 6983 | 7044 | try self.asmRegisterMemory( |
| 6984 | 7045 | .lea, |
| 6985 | 7046 | registerAlias(reg, abi_size), |
| ... | ... | @@ -7158,10 +7219,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7158 | 7219 | }, |
| 7159 | 7220 | }, |
| 7160 | 7221 | .stack_offset => |off| { |
| 7161 | | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 7162 | | return self.fail("stack offset too large", .{}); |
| 7163 | | } |
| 7164 | | |
| 7165 | 7222 | switch (ty.zigTypeTag()) { |
| 7166 | 7223 | .Int => switch (ty.intInfo(self.target.*).signedness) { |
| 7167 | 7224 | .signed => { |