| ... | @@ -621,8 +621,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -621,8 +621,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 621 | .trunc_float, | 621 | .trunc_float, |
| 622 | => try self.airUnaryMath(inst), | 622 | => try self.airUnaryMath(inst), |
| 623 | | 623 | |
| 624 | .add_with_overflow => try self.airAddWithOverflow(inst), | 624 | .add_with_overflow => try self.airAddSubWithOverflow(inst), |
| 625 | .sub_with_overflow => try self.airSubWithOverflow(inst), | 625 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), |
| 626 | .mul_with_overflow => try self.airMulWithOverflow(inst), | 626 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| 627 | .shl_with_overflow => try self.airShlWithOverflow(inst), | 627 | .shl_with_overflow => try self.airShlWithOverflow(inst), |
| 628 | | 628 | |
| ... | @@ -1279,8 +1279,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1279,8 +1279,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1279 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1279 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1280 | } | 1280 | } |
| 1281 | | 1281 | |
| 1282 | fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 1282 | fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1283 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1283 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 1284 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1284 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1285 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1285 | const result = if (self.liveness.isUnused(inst)) .dead else result: { | 1286 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1286 | const ty = self.air.typeOf(bin_op.lhs); | 1287 | const ty = self.air.typeOf(bin_op.lhs); |
| ... | @@ -1300,42 +1301,12 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1300,42 +1301,12 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1300 | const lhs = try self.resolveInst(bin_op.lhs); | 1301 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1301 | const rhs = try self.resolveInst(bin_op.rhs); | 1302 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1302 | | 1303 | |
| 1303 | const partial = try self.genBinOp(.add, null, lhs, rhs, ty, ty); | 1304 | const base_tag: Air.Inst.Tag = switch (tag) { |
| 1304 | const result: MCValue = switch (int_info.signedness) { | 1305 | .add_with_overflow => .add, |
| 1305 | .signed => .{ .register_overflow_signed = partial.register }, | 1306 | .sub_with_overflow => .sub, |
| 1306 | .unsigned => .{ .register_overflow_unsigned = partial.register }, | 1307 | else => unreachable, |
| 1307 | }; | 1308 | }; |
| 1308 | break :result result; | 1309 | const partial = try self.genBinOp(base_tag, null, lhs, rhs, ty, ty); |
| 1309 | }, | | |
| 1310 | else => unreachable, | | |
| 1311 | } | | |
| 1312 | }; | | |
| 1313 | | | |
| 1314 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 1315 | } | | |
| 1316 | | | |
| 1317 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | | |
| 1318 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | | |
| 1319 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | | |
| 1320 | const result = if (self.liveness.isUnused(inst)) .dead else result: { | | |
| 1321 | const ty = self.air.typeOf(bin_op.lhs); | | |
| 1322 | | | |
| 1323 | switch (ty.zigTypeTag()) { | | |
| 1324 | .Vector => return self.fail("TODO implement sub_with_overflow for Vector type", .{}), | | |
| 1325 | .Int => { | | |
| 1326 | const int_info = ty.intInfo(self.target.*); | | |
| 1327 | | | |
| 1328 | if (int_info.bits > 64) { | | |
| 1329 | return self.fail("TODO implement sub_with_overflow for Ints larger than 64bits", .{}); | | |
| 1330 | } | | |
| 1331 | | | |
| 1332 | try self.spillCompareFlagsIfOccupied(); | | |
| 1333 | self.compare_flags_inst = inst; | | |
| 1334 | | | |
| 1335 | const lhs = try self.resolveInst(bin_op.lhs); | | |
| 1336 | const rhs = try self.resolveInst(bin_op.rhs); | | |
| 1337 | | | |
| 1338 | const partial = try self.genBinOp(.sub, null, lhs, rhs, ty, ty); | | |
| 1339 | const result: MCValue = switch (int_info.signedness) { | 1310 | const result: MCValue = switch (int_info.signedness) { |
| 1340 | .signed => .{ .register_overflow_signed = partial.register }, | 1311 | .signed => .{ .register_overflow_signed = partial.register }, |
| 1341 | .unsigned => .{ .register_overflow_unsigned = partial.register }, | 1312 | .unsigned => .{ .register_overflow_unsigned = partial.register }, |