| ... | @@ -1414,23 +1414,27 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1414,23 +1414,27 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1414 | fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 1414 | fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1415 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1415 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1416 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1416 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 1417 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1418 | const ty = self.air.typeOf(bin_op.lhs); |
| 1417 | | 1419 | |
| 1418 | if (self.liveness.isUnused(inst)) { | 1420 | switch (ty.zigTypeTag()) { |
| 1419 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 1421 | .Vector => return self.fail("TODO implement add_with_overflow for Vector type", .{}), |
| 1420 | } | 1422 | .Int => { |
| | 1423 | const int_info = ty.intInfo(self.target.*); |
| 1421 | | 1424 | |
| 1422 | const ty = self.air.typeOf(bin_op.lhs); | 1425 | if (int_info.bits > 64) { |
| 1423 | const signedness: std.builtin.Signedness = blk: { | 1426 | return self.fail("TODO implement add_with_overflow for Ints larger than 64bits", .{}); |
| 1424 | if (ty.zigTypeTag() != .Int) { | 1427 | } |
| 1425 | return self.fail("TODO implement airAddWithOverflow for type {}", .{ty.fmtDebug()}); | | |
| 1426 | } | | |
| 1427 | break :blk ty.intInfo(self.target.*).signedness; | | |
| 1428 | }; | | |
| 1429 | | 1428 | |
| 1430 | const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs); | 1429 | const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1431 | const result: MCValue = switch (signedness) { | 1430 | const result: MCValue = switch (int_info.signedness) { |
| 1432 | .signed => .{ .register_overflow_signed = partial.register }, | 1431 | .signed => .{ .register_overflow_signed = partial.register }, |
| 1433 | .unsigned => .{ .register_overflow_unsigned = partial.register }, | 1432 | .unsigned => .{ .register_overflow_unsigned = partial.register }, |
| | 1433 | }; |
| | 1434 | break :result result; |
| | 1435 | }, |
| | 1436 | else => unreachable, |
| | 1437 | } |
| 1434 | }; | 1438 | }; |
| 1435 | | 1439 | |
| 1436 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1440 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -1439,23 +1443,27 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1439,23 +1443,27 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1439 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 1443 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1440 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1444 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1441 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1445 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 1446 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1447 | const ty = self.air.typeOf(bin_op.lhs); |
| 1442 | | 1448 | |
| 1443 | if (self.liveness.isUnused(inst)) { | 1449 | switch (ty.zigTypeTag()) { |
| 1444 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 1450 | .Vector => return self.fail("TODO implement sub_with_overflow for Vector type", .{}), |
| 1445 | } | 1451 | .Int => { |
| | 1452 | const int_info = ty.intInfo(self.target.*); |
| 1446 | | 1453 | |
| 1447 | const ty = self.air.typeOf(bin_op.lhs); | 1454 | if (int_info.bits > 64) { |
| 1448 | const signedness: std.builtin.Signedness = blk: { | 1455 | return self.fail("TODO implement sub_with_overflow for Ints larger than 64bits", .{}); |
| 1449 | if (ty.zigTypeTag() != .Int) { | 1456 | } |
| 1450 | return self.fail("TODO implement airSubWithOverflow for type {}", .{ty.fmtDebug()}); | | |
| 1451 | } | | |
| 1452 | break :blk ty.intInfo(self.target.*).signedness; | | |
| 1453 | }; | | |
| 1454 | | 1457 | |
| 1455 | const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs); | 1458 | const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs); |
| 1456 | const result: MCValue = switch (signedness) { | 1459 | const result: MCValue = switch (int_info.signedness) { |
| 1457 | .signed => .{ .register_overflow_signed = partial.register }, | 1460 | .signed => .{ .register_overflow_signed = partial.register }, |
| 1458 | .unsigned => .{ .register_overflow_unsigned = partial.register }, | 1461 | .unsigned => .{ .register_overflow_unsigned = partial.register }, |
| | 1462 | }; |
| | 1463 | break :result result; |
| | 1464 | }, |
| | 1465 | else => unreachable, |
| | 1466 | } |
| 1459 | }; | 1467 | }; |
| 1460 | | 1468 | |
| 1461 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1469 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -1466,30 +1474,37 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1466,30 +1474,37 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1466 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1474 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1467 | const result = if (self.liveness.isUnused(inst)) .dead else result: { | 1475 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1468 | const ty = self.air.typeOf(bin_op.lhs); | 1476 | const ty = self.air.typeOf(bin_op.lhs); |
| 1469 | const signedness: std.builtin.Signedness = blk: { | | |
| 1470 | if (ty.zigTypeTag() != .Int) { | | |
| 1471 | return self.fail("TODO implement airMulWithOverflow for type {}", .{ty.fmtDebug()}); | | |
| 1472 | } | | |
| 1473 | break :blk ty.intInfo(self.target.*).signedness; | | |
| 1474 | }; | | |
| 1475 | | 1477 | |
| 1476 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1478 | switch (ty.zigTypeTag()) { |
| 1477 | try self.register_manager.getReg(.rax, inst); | 1479 | .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}), |
| 1478 | try self.register_manager.getReg(.rdx, null); | 1480 | .Int => { |
| 1479 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); | 1481 | const int_info = ty.intInfo(self.target.*); |
| 1480 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); | | |
| 1481 | | 1482 | |
| 1482 | const lhs = try self.resolveInst(bin_op.lhs); | 1483 | if (int_info.bits > 64) { |
| 1483 | const rhs = try self.resolveInst(bin_op.rhs); | 1484 | return self.fail("TODO implement mul_with_overflow for Ints larger than 64bits", .{}); |
| | 1485 | } |
| 1484 | | 1486 | |
| 1485 | try self.genIntMulDivOpMir(switch (signedness) { | 1487 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1486 | .signed => .imul, | 1488 | try self.register_manager.getReg(.rax, inst); |
| 1487 | .unsigned => .mul, | 1489 | try self.register_manager.getReg(.rdx, null); |
| 1488 | }, ty, signedness, lhs, rhs); | 1490 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1491 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| 1489 | | 1492 | |
| 1490 | switch (signedness) { | 1493 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1491 | .signed => break :result MCValue{ .register_overflow_signed = .rax }, | 1494 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1492 | .unsigned => break :result MCValue{ .register_overflow_unsigned = .rax }, | 1495 | |
| | 1496 | try self.genIntMulDivOpMir(switch (int_info.signedness) { |
| | 1497 | .signed => .imul, |
| | 1498 | .unsigned => .mul, |
| | 1499 | }, ty, int_info.signedness, lhs, rhs); |
| | 1500 | |
| | 1501 | const result: MCValue = switch (int_info.signedness) { |
| | 1502 | .signed => .{ .register_overflow_signed = .rax }, |
| | 1503 | .unsigned => .{ .register_overflow_unsigned = .rax }, |
| | 1504 | }; |
| | 1505 | break :result result; |
| | 1506 | }, |
| | 1507 | else => unreachable, |
| 1493 | } | 1508 | } |
| 1494 | }; | 1509 | }; |
| 1495 | | 1510 | |