| ... | @@ -1457,8 +1457,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1457,8 +1457,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1457 | } | 1457 | } |
| 1458 | | 1458 | |
| 1459 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 1459 | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1460 | _ = inst; | 1460 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1461 | return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch}); | 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 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | 1510 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { |