| ... | ... | @@ -1457,8 +1457,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1457 | 1457 | } |
| 1458 | 1458 | |
| 1459 | 1459 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1460 | | _ = inst; |
| 1461 | | return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch}); |
| 1460 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1461 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1462 | if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); |
| 1463 | const result: MCValue = result: { |
| 1464 | const lhs = try self.resolveInst(extra.lhs); |
| 1465 | const rhs = try self.resolveInst(extra.rhs); |
| 1466 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 1467 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 1468 | |
| 1469 | const tuple_ty = self.air.typeOfIndex(inst); |
| 1470 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); |
| 1471 | const tuple_align = tuple_ty.abiAlignment(self.target.*); |
| 1472 | const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*)); |
| 1473 | |
| 1474 | switch (lhs_ty.zigTypeTag()) { |
| 1475 | .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), |
| 1476 | .Int => { |
| 1477 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1478 | if (int_info.bits <= 32) { |
| 1479 | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| 1480 | |
| 1481 | if (lhs == .register) self.register_manager.freezeRegs(&.{lhs.register}); |
| 1482 | defer if (lhs == .register) self.register_manager.unfreezeRegs(&.{lhs.register}); |
| 1483 | |
| 1484 | try self.spillCompareFlagsIfOccupied(); |
| 1485 | self.compare_flags_inst = null; |
| 1486 | |
| 1487 | // lsl dest, lhs, rhs |
| 1488 | const dest = try self.binOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty); |
| 1489 | |
| 1490 | // asr/lsr reconstructed, dest, rhs |
| 1491 | const reconstructed = try self.binOp(.shr, null, dest, rhs, lhs_ty, rhs_ty); |
| 1492 | |
| 1493 | // cmp lhs, reconstructed |
| 1494 | _ = try self.binOp(.cmp_eq, null, lhs, reconstructed, lhs_ty, lhs_ty); |
| 1495 | |
| 1496 | try self.genSetStack(lhs_ty, stack_offset, dest); |
| 1497 | try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq }); |
| 1498 | |
| 1499 | break :result MCValue{ .stack_offset = stack_offset }; |
| 1500 | } else { |
| 1501 | return self.fail("TODO ARM overflow operations on integers > u32/i32", .{}); |
| 1502 | } |
| 1503 | }, |
| 1504 | else => unreachable, |
| 1505 | } |
| 1506 | }; |
| 1507 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 1462 | 1508 | } |
| 1463 | 1509 | |
| 1464 | 1510 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { |