Skip to content

Commit 5b4de16

Browse files
committed
x64: explicitly handle Vector vs Int types for overflow arith
1 parent 59905a6 commit 5b4de16

File tree

1 file changed

+63
-48
lines changed

1 file changed

+63
-48
lines changed

src/arch/x86_64/CodeGen.zig

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,23 +1414,27 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
14141414
fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14151415
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
14161416
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);
14171419

1418-
if (self.liveness.isUnused(inst)) {
1419-
return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1420-
}
1420+
switch (ty.zigTypeTag()) {
1421+
.Vector => return self.fail("TODO implement add_with_overflow for Vector type", .{}),
1422+
.Int => {
1423+
const int_info = ty.intInfo(self.target.*);
14211424

1422-
const ty = self.air.typeOf(bin_op.lhs);
1423-
const signedness: std.builtin.Signedness = blk: {
1424-
if (ty.zigTypeTag() != .Int) {
1425-
return self.fail("TODO implement airAddWithOverflow for type {}", .{ty.fmtDebug()});
1426-
}
1427-
break :blk ty.intInfo(self.target.*).signedness;
1428-
};
1425+
if (int_info.bits > 64) {
1426+
return self.fail("TODO implement add_with_overflow for Ints larger than 64bits", .{});
1427+
}
14291428

1430-
const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1431-
const result: MCValue = switch (signedness) {
1432-
.signed => .{ .register_overflow_signed = partial.register },
1433-
.unsigned => .{ .register_overflow_unsigned = partial.register },
1429+
const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1430+
const result: MCValue = switch (int_info.signedness) {
1431+
.signed => .{ .register_overflow_signed = partial.register },
1432+
.unsigned => .{ .register_overflow_unsigned = partial.register },
1433+
};
1434+
break :result result;
1435+
},
1436+
else => unreachable,
1437+
}
14341438
};
14351439

14361440
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 {
14391443
fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14401444
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
14411445
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);
14421448

1443-
if (self.liveness.isUnused(inst)) {
1444-
return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1445-
}
1449+
switch (ty.zigTypeTag()) {
1450+
.Vector => return self.fail("TODO implement sub_with_overflow for Vector type", .{}),
1451+
.Int => {
1452+
const int_info = ty.intInfo(self.target.*);
14461453

1447-
const ty = self.air.typeOf(bin_op.lhs);
1448-
const signedness: std.builtin.Signedness = blk: {
1449-
if (ty.zigTypeTag() != .Int) {
1450-
return self.fail("TODO implement airSubWithOverflow for type {}", .{ty.fmtDebug()});
1451-
}
1452-
break :blk ty.intInfo(self.target.*).signedness;
1453-
};
1454+
if (int_info.bits > 64) {
1455+
return self.fail("TODO implement sub_with_overflow for Ints larger than 64bits", .{});
1456+
}
14541457

1455-
const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);
1456-
const result: MCValue = switch (signedness) {
1457-
.signed => .{ .register_overflow_signed = partial.register },
1458-
.unsigned => .{ .register_overflow_unsigned = partial.register },
1458+
const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);
1459+
const result: MCValue = switch (int_info.signedness) {
1460+
.signed => .{ .register_overflow_signed = partial.register },
1461+
.unsigned => .{ .register_overflow_unsigned = partial.register },
1462+
};
1463+
break :result result;
1464+
},
1465+
else => unreachable,
1466+
}
14591467
};
14601468

14611469
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 {
14661474
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
14671475
const result = if (self.liveness.isUnused(inst)) .dead else result: {
14681476
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-
};
14751477

1476-
// Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1477-
try self.register_manager.getReg(.rax, inst);
1478-
try self.register_manager.getReg(.rdx, null);
1479-
self.register_manager.freezeRegs(&.{ .rax, .rdx });
1480-
defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
1478+
switch (ty.zigTypeTag()) {
1479+
.Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),
1480+
.Int => {
1481+
const int_info = ty.intInfo(self.target.*);
14811482

1482-
const lhs = try self.resolveInst(bin_op.lhs);
1483-
const rhs = try self.resolveInst(bin_op.rhs);
1483+
if (int_info.bits > 64) {
1484+
return self.fail("TODO implement mul_with_overflow for Ints larger than 64bits", .{});
1485+
}
14841486

1485-
try self.genIntMulDivOpMir(switch (signedness) {
1486-
.signed => .imul,
1487-
.unsigned => .mul,
1488-
}, ty, signedness, lhs, rhs);
1487+
// Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1488+
try self.register_manager.getReg(.rax, inst);
1489+
try self.register_manager.getReg(.rdx, null);
1490+
self.register_manager.freezeRegs(&.{ .rax, .rdx });
1491+
defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
14891492

1490-
switch (signedness) {
1491-
.signed => break :result MCValue{ .register_overflow_signed = .rax },
1492-
.unsigned => break :result MCValue{ .register_overflow_unsigned = .rax },
1493+
const lhs = try self.resolveInst(bin_op.lhs);
1494+
const rhs = try self.resolveInst(bin_op.rhs);
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,
14931508
}
14941509
};
14951510

0 commit comments

Comments
 (0)