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