| ... | ... | @@ -1314,6 +1314,9 @@ fn binOpRegister( |
| 1314 | 1314 | const lhs_is_register = lhs == .register; |
| 1315 | 1315 | const rhs_is_register = rhs == .register; |
| 1316 | 1316 | |
| 1317 | if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*))); |
| 1318 | if (rhs_is_register) assert(rhs.register == registerAlias(rhs.register, rhs_ty.abiSize(self.target.*))); |
| 1319 | |
| 1317 | 1320 | const lhs_lock: ?RegisterLock = if (lhs_is_register) |
| 1318 | 1321 | self.register_manager.lockReg(lhs.register) |
| 1319 | 1322 | else |
| ... | ... | @@ -1343,13 +1346,22 @@ fn binOpRegister( |
| 1343 | 1346 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 1344 | 1347 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1345 | 1348 | |
| 1346 | | const rhs_reg = if (rhs_is_register) rhs.register else blk: { |
| 1349 | const rhs_reg = if (rhs_is_register) |
| 1350 | // lhs is almost always equal to rhs, except in shifts. In |
| 1351 | // order to guarantee that registers will have equal sizes, we |
| 1352 | // use the register alias of rhs corresponding to the size of |
| 1353 | // lhs. |
| 1354 | registerAlias(rhs.register, lhs_ty.abiSize(self.target.*)) |
| 1355 | else blk: { |
| 1347 | 1356 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 1348 | 1357 | break :inst Air.refToIndex(md.rhs).?; |
| 1349 | 1358 | } else null; |
| 1350 | 1359 | |
| 1351 | 1360 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1352 | | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); |
| 1361 | |
| 1362 | // Here, we deliberately use lhs as lhs and rhs may differ in |
| 1363 | // the case of shifts. See comment above. |
| 1364 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1353 | 1365 | |
| 1354 | 1366 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1355 | 1367 | |
| ... | ... | @@ -1458,6 +1470,8 @@ fn binOpImmediate( |
| 1458 | 1470 | ) !MCValue { |
| 1459 | 1471 | const lhs_is_register = lhs == .register; |
| 1460 | 1472 | |
| 1473 | if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*))); |
| 1474 | |
| 1461 | 1475 | const lhs_lock: ?RegisterLock = if (lhs_is_register) |
| 1462 | 1476 | self.register_manager.lockReg(lhs.register) |
| 1463 | 1477 | else |
| ... | ... | @@ -1698,21 +1712,52 @@ fn binOp( |
| 1698 | 1712 | null; |
| 1699 | 1713 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1700 | 1714 | |
| 1701 | | const lhs_reg = if (lhs_is_register) |
| 1702 | | lhs.register |
| 1715 | const rhs_lock: ?RegisterLock = if (rhs_is_register) |
| 1716 | self.register_manager.lockReg(rhs.register) |
| 1703 | 1717 | else |
| 1704 | | try self.register_manager.allocReg(null, gp); |
| 1718 | null; |
| 1719 | defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1720 | |
| 1721 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 1722 | |
| 1723 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| 1724 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 1725 | break :inst Air.refToIndex(md.lhs).?; |
| 1726 | } else null; |
| 1727 | |
| 1728 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1729 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1730 | |
| 1731 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1732 | |
| 1733 | break :blk reg; |
| 1734 | }; |
| 1705 | 1735 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 1706 | 1736 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1707 | 1737 | |
| 1708 | | const rhs_reg = if (rhs_is_register) |
| 1709 | | rhs.register |
| 1710 | | else |
| 1711 | | try self.register_manager.allocReg(null, gp); |
| 1738 | const rhs_reg = if (rhs_is_register) rhs.register else blk: { |
| 1739 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 1740 | break :inst Air.refToIndex(md.rhs).?; |
| 1741 | } else null; |
| 1742 | |
| 1743 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1744 | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); |
| 1745 | |
| 1746 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1747 | |
| 1748 | break :blk reg; |
| 1749 | }; |
| 1712 | 1750 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); |
| 1713 | 1751 | defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1714 | 1752 | |
| 1715 | | const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 1753 | const dest_regs: [2]Register = blk: { |
| 1754 | const raw_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 1755 | const abi_size = lhs_ty.abiSize(self.target.*); |
| 1756 | break :blk .{ |
| 1757 | registerAlias(raw_regs[0], abi_size), |
| 1758 | registerAlias(raw_regs[1], abi_size), |
| 1759 | }; |
| 1760 | }; |
| 1716 | 1761 | const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs); |
| 1717 | 1762 | defer for (dest_regs_locks) |reg| { |
| 1718 | 1763 | self.register_manager.unlockReg(reg); |
| ... | ... | @@ -2037,7 +2082,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2037 | 2082 | try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits); |
| 2038 | 2083 | |
| 2039 | 2084 | // cmp dest, truncated |
| 2040 | | _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null); |
| 2085 | _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, lhs_ty, lhs_ty, null); |
| 2041 | 2086 | |
| 2042 | 2087 | try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg }); |
| 2043 | 2088 | try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne }); |
| ... | ... | @@ -2753,7 +2798,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2753 | 2798 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2754 | 2799 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 2755 | 2800 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2756 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch}); |
| 2801 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2802 | const ptr_mcv = try self.resolveInst(extra.lhs); |
| 2803 | const index_mcv = try self.resolveInst(extra.rhs); |
| 2804 | |
| 2805 | const ptr_ty = self.air.typeOf(extra.lhs); |
| 2806 | |
| 2807 | const addr = try self.binOp(.ptr_add, ptr_mcv, index_mcv, ptr_ty, Type.usize, null); |
| 2808 | break :result addr; |
| 2809 | }; |
| 2757 | 2810 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 2758 | 2811 | } |
| 2759 | 2812 | |
| ... | ... | @@ -3219,6 +3272,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3219 | 3272 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 3220 | 3273 | const mcv = try self.resolveInst(operand); |
| 3221 | 3274 | const struct_ty = self.air.typeOf(operand); |
| 3275 | const struct_field_ty = struct_ty.structFieldType(index); |
| 3222 | 3276 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 3223 | 3277 | |
| 3224 | 3278 | switch (mcv) { |
| ... | ... | @@ -3250,8 +3304,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3250 | 3304 | break :result field; |
| 3251 | 3305 | } else { |
| 3252 | 3306 | // Copy to new register |
| 3253 | | const dest_reg = try self.register_manager.allocReg(null, gp); |
| 3254 | | try self.genSetReg(struct_ty.structFieldType(index), dest_reg, field); |
| 3307 | const raw_dest_reg = try self.register_manager.allocReg(null, gp); |
| 3308 | const dest_reg = registerAlias(raw_dest_reg, struct_field_ty.abiSize(self.target.*)); |
| 3309 | try self.genSetReg(struct_field_ty, dest_reg, field); |
| 3255 | 3310 | |
| 3256 | 3311 | break :result MCValue{ .register = dest_reg }; |
| 3257 | 3312 | } |