| ... | @@ -1184,28 +1184,36 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1184,28 +1184,36 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1184 | const lhs_ty = self.typeOf(extra.lhs); | 1184 | const lhs_ty = self.typeOf(extra.lhs); |
| 1185 | const rhs_ty = self.typeOf(extra.rhs); | 1185 | const rhs_ty = self.typeOf(extra.rhs); |
| 1186 | | 1186 | |
| 1187 | const partial_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty); | 1187 | const add_result_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty); |
| 1188 | | 1188 | |
| 1189 | const tuple_ty = self.typeOfIndex(inst); | 1189 | const tuple_ty = self.typeOfIndex(inst); |
| | 1190 | const int_info = lhs_ty.intInfo(mod); |
| 1190 | | 1191 | |
| 1191 | // TODO: optimization, set this to true. needs the other struct access stuff to support | 1192 | // TODO: optimization, set this to true. needs the other struct access stuff to support |
| 1192 | // accessing registers. | 1193 | // accessing registers. |
| 1193 | const result_mcv = try self.allocRegOrMem(inst, false); | 1194 | const result_mcv = try self.allocRegOrMem(inst, false); |
| 1194 | const offset = result_mcv.stack_offset; | 1195 | const offset = result_mcv.stack_offset; |
| 1195 | | 1196 | |
| 1196 | const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset; | | |
| 1197 | const result_offset = tuple_ty.structFieldOffset(0, mod) + offset; | 1197 | const result_offset = tuple_ty.structFieldOffset(0, mod) + offset; |
| 1198 | | 1198 | |
| 1199 | const overflow_mcv = try self.binOp(.cmp_lt, null, partial_mcv, lhs, lhs_ty, lhs_ty); | 1199 | // set the result first as we don't have a lock on the add_result_mcv register and it will |
| | 1200 | // get clobbered in the next binOp. |
| | 1201 | try self.genSetStack(lhs_ty, @intCast(result_offset), add_result_mcv); |
| 1200 | | 1202 | |
| 1201 | const overflow_reg, const overflow_lock = try self.allocReg(); | 1203 | if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { |
| 1202 | defer self.register_manager.unlockReg(overflow_lock); | 1204 | if (int_info.signedness == .unsigned) { |
| | 1205 | const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset; |
| 1203 | | 1206 | |
| 1204 | try self.genSetReg(lhs_ty, overflow_reg, overflow_mcv); | 1207 | const overflow_mcv = try self.binOp(.cmp_lt, null, add_result_mcv, lhs, lhs_ty, lhs_ty); |
| | 1208 | try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv); |
| 1205 | | 1209 | |
| 1206 | try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv); | 1210 | break :result result_mcv; |
| 1207 | try self.genSetStack(lhs_ty, @intCast(result_offset), partial_mcv); | 1211 | } else { |
| 1208 | break :result result_mcv; | 1212 | return self.fail("TODO: airAddWithOverFlow calculate carry for signed addition", .{}); |
| | 1213 | } |
| | 1214 | } else { |
| | 1215 | return self.fail("TODO: airAddWithOverflow with < 8 bits or non-pow of 2", .{}); |
| | 1216 | } |
| 1209 | }; | 1217 | }; |
| 1210 | | 1218 | |
| 1211 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 1219 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| ... | @@ -1716,9 +1724,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -1716,9 +1724,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 1716 | | 1724 | |
| 1717 | /// Loads `value` into the "payload" of `pointer`. | 1725 | /// Loads `value` into the "payload" of `pointer`. |
| 1718 | fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { | 1726 | fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { |
| 1719 | _ = ptr_ty; | | |
| 1720 | const mod = self.bin_file.comp.module.?; | 1727 | const mod = self.bin_file.comp.module.?; |
| 1721 | const value_size = value_ty.abiSize(mod); | 1728 | const value_abi_size = value_ty.abiSize(mod); |
| 1722 | | 1729 | |
| 1723 | log.debug("storing {s}", .{@tagName(pointer)}); | 1730 | log.debug("storing {s}", .{@tagName(pointer)}); |
| 1724 | | 1731 | |
| ... | @@ -1741,9 +1748,9 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: | ... | @@ -1741,9 +1748,9 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: |
| 1741 | .register => |reg| { | 1748 | .register => |reg| { |
| 1742 | const value_reg = try self.copyToTmpRegister(value_ty, value); | 1749 | const value_reg = try self.copyToTmpRegister(value_ty, value); |
| 1743 | | 1750 | |
| 1744 | switch (value_size) { | 1751 | switch (value_abi_size) { |
| 1745 | 1, 2, 4, 8 => { | 1752 | 1, 2, 4, 8 => { |
| 1746 | const tag: Mir.Inst.Tag = switch (value_size) { | 1753 | const tag: Mir.Inst.Tag = switch (value_abi_size) { |
| 1747 | 1 => .sb, | 1754 | 1 => .sb, |
| 1748 | 2 => .sh, | 1755 | 2 => .sh, |
| 1749 | 4 => .sw, | 1756 | 4 => .sw, |
| ... | @@ -1760,7 +1767,7 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: | ... | @@ -1760,7 +1767,7 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: |
| 1760 | } }, | 1767 | } }, |
| 1761 | }); | 1768 | }); |
| 1762 | }, | 1769 | }, |
| 1763 | else => return self.fail("TODO: genSetStack for size={d}", .{value_size}), | 1770 | else => return self.fail("TODO: genSetStack for size={d}", .{value_abi_size}), |
| 1764 | } | 1771 | } |
| 1765 | }, | 1772 | }, |
| 1766 | else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}), | 1773 | else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}), |
| ... | @@ -1842,7 +1849,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1842,7 +1849,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1842 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); | 1849 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); |
| 1843 | }, | 1850 | }, |
| 1844 | .stack_offset => |off| { | 1851 | .stack_offset => |off| { |
| 1845 | break :result MCValue{ .stack_offset = off + field_off }; | 1852 | log.debug("airStructFieldVal off: {}", .{field_off}); |
| | 1853 | const field_byte_off: u32 = @divExact(field_off, 8); |
| | 1854 | break :result MCValue{ .stack_offset = off + field_byte_off }; |
| 1846 | }, | 1855 | }, |
| 1847 | else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}), | 1856 | else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}), |
| 1848 | } | 1857 | } |