authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-15 19:09:57-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-04-20 20:49:35+01:00
log9f1409cabc6545d977defa4f22967eb5f1a202a0
tree0e96b813bbe0cf1c9271e17d571d03178ce3cc62
parentd5879ad1d00799a644741bfc207f31f944b3ce86
signaturelock-open Commit is signed but in an unrecognized format.

x86_64: adapt to new isUnused liveness change


1 files changed, 970 insertions(+), 1123 deletions(-)

src/arch/x86_64/CodeGen.zig+970-1123
...@@ -917,17 +917,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -917,17 +917,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
917 const air_tags = self.air.instructions.items(.tag);917 const air_tags = self.air.instructions.items(.tag);
918918
919 for (body) |inst| {919 for (body) |inst| {
920 // TODO: remove now-redundant isUnused calls from AIR handler functions
921 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
922 continue;
923 }
924
925 const old_air_bookkeeping = self.air_bookkeeping;
926 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
927 if (builtin.mode == .Debug) {920 if (builtin.mode == .Debug) {
928 const mir_inst = @intCast(Mir.Inst.Index, self.mir_instructions.len);921 const mir_inst = @intCast(Mir.Inst.Index, self.mir_instructions.len);
929 try self.mir_to_air_map.put(self.gpa, mir_inst, inst);922 try self.mir_to_air_map.put(self.gpa, mir_inst, inst);
930 }923 }
924
925 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) continue;
931 if (debug_wip_mir) @import("../../print_air.zig").dumpInst(926 if (debug_wip_mir) @import("../../print_air.zig").dumpInst(
932 inst,927 inst,
933 self.bin_file.options.module.?,928 self.bin_file.options.module.?,
...@@ -935,6 +930,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -935,6 +930,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
935 self.liveness,930 self.liveness,
936 );931 );
937932
933 const old_air_bookkeeping = self.air_bookkeeping;
934 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
938 switch (air_tags[inst]) {935 switch (air_tags[inst]) {
939 // zig fmt: off936 // zig fmt: off
940 .not,937 .not,
...@@ -1505,22 +1502,14 @@ fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Ty...@@ -1505,22 +1502,14 @@ fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Ty
1505}1502}
15061503
1507fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {1504fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
1508 const result: MCValue = result: {1505 const stack_offset = try self.allocMemPtr(inst);
1509 if (self.liveness.isUnused(inst)) break :result .unreach;1506 const result = MCValue{ .ptr_stack_offset = @intCast(i32, stack_offset) };
1510
1511 const stack_offset = try self.allocMemPtr(inst);
1512 break :result .{ .ptr_stack_offset = @intCast(i32, stack_offset) };
1513 };
1514 return self.finishAir(inst, result, .{ .none, .none, .none });1507 return self.finishAir(inst, result, .{ .none, .none, .none });
1515}1508}
15161509
1517fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1510fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1518 const result: MCValue = result: {1511 const stack_offset = try self.allocMemPtr(inst);
1519 if (self.liveness.isUnused(inst)) break :result .unreach;1512 const result = MCValue{ .ptr_stack_offset = @intCast(i32, stack_offset) };
1520
1521 const stack_offset = try self.allocMemPtr(inst);
1522 break :result .{ .ptr_stack_offset = @intCast(i32, stack_offset) };
1523 };
1524 return self.finishAir(inst, result, .{ .none, .none, .none });1513 return self.finishAir(inst, result, .{ .none, .none, .none });
1525}1514}
15261515
...@@ -1540,126 +1529,125 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -1540,126 +1529,125 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
15401529
1541fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {1530fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1542 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1531 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1543 const result = if (self.liveness.isUnused(inst)) .unreach else result: {
1544 const src_ty = self.air.typeOf(ty_op.operand);
1545 const src_int_info = src_ty.intInfo(self.target.*);
1546 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
1547 const src_mcv = try self.resolveInst(ty_op.operand);
1548 const src_lock = switch (src_mcv) {
1549 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1550 else => null,
1551 };
1552 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1553
1554 const dst_ty = self.air.typeOfIndex(inst);
1555 const dst_int_info = dst_ty.intInfo(self.target.*);
1556 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
1557 const dst_mcv = if (dst_abi_size <= src_abi_size and
1558 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
1559 src_mcv
1560 else
1561 try self.allocRegOrMem(inst, true);
15621532
1563 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;1533 const src_ty = self.air.typeOf(ty_op.operand);
1564 const signedness: std.builtin.Signedness = if (dst_int_info.signedness == .signed and1534 const src_int_info = src_ty.intInfo(self.target.*);
1565 src_int_info.signedness == .signed) .signed else .unsigned;1535 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
1566 switch (dst_mcv) {1536 const src_mcv = try self.resolveInst(ty_op.operand);
1567 .register => |dst_reg| {1537 const src_lock = switch (src_mcv) {
1568 const min_abi_size = @min(dst_abi_size, src_abi_size);1538 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1569 const tag: Mir.Inst.Tag = switch (signedness) {1539 else => null,
1570 .signed => .movsx,
1571 .unsigned => if (min_abi_size > 2) .mov else .movzx,
1572 };
1573 const dst_alias = switch (tag) {
1574 .movsx => dst_reg.to64(),
1575 .mov, .movzx => if (min_abi_size > 4) dst_reg.to64() else dst_reg.to32(),
1576 else => unreachable,
1577 };
1578 switch (src_mcv) {
1579 .register => |src_reg| {
1580 try self.asmRegisterRegister(
1581 tag,
1582 dst_alias,
1583 registerAlias(src_reg, min_abi_size),
1584 );
1585 },
1586 .stack_offset => |src_off| {
1587 try self.asmRegisterMemory(tag, dst_alias, Memory.sib(
1588 Memory.PtrSize.fromSize(min_abi_size),
1589 .{ .base = .rbp, .disp = -src_off },
1590 ));
1591 },
1592 else => return self.fail("TODO airIntCast from {s} to {s}", .{
1593 @tagName(src_mcv),
1594 @tagName(dst_mcv),
1595 }),
1596 }
1597 if (self.regExtraBits(min_ty) > 0) try self.truncateRegister(min_ty, dst_reg);
1598 },
1599 else => {
1600 try self.setRegOrMem(min_ty, dst_mcv, src_mcv);
1601 const extra = dst_abi_size * 8 - dst_int_info.bits;
1602 if (extra > 0) {
1603 try self.genShiftBinOpMir(switch (signedness) {
1604 .signed => .sal,
1605 .unsigned => .shl,
1606 }, dst_ty, dst_mcv, .{ .immediate = extra });
1607 try self.genShiftBinOpMir(switch (signedness) {
1608 .signed => .sar,
1609 .unsigned => .shr,
1610 }, dst_ty, dst_mcv, .{ .immediate = extra });
1611 }
1612 },
1613 }
1614 break :result dst_mcv;
1615 };1540 };
1616 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1541 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1542
1543 const dst_ty = self.air.typeOfIndex(inst);
1544 const dst_int_info = dst_ty.intInfo(self.target.*);
1545 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
1546 const dst_mcv = if (dst_abi_size <= src_abi_size and
1547 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
1548 src_mcv
1549 else
1550 try self.allocRegOrMem(inst, true);
1551
1552 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;
1553 const signedness: std.builtin.Signedness = if (dst_int_info.signedness == .signed and
1554 src_int_info.signedness == .signed) .signed else .unsigned;
1555 switch (dst_mcv) {
1556 .register => |dst_reg| {
1557 const min_abi_size = @min(dst_abi_size, src_abi_size);
1558 const tag: Mir.Inst.Tag = switch (signedness) {
1559 .signed => .movsx,
1560 .unsigned => if (min_abi_size > 2) .mov else .movzx,
1561 };
1562 const dst_alias = switch (tag) {
1563 .movsx => dst_reg.to64(),
1564 .mov, .movzx => if (min_abi_size > 4) dst_reg.to64() else dst_reg.to32(),
1565 else => unreachable,
1566 };
1567 switch (src_mcv) {
1568 .register => |src_reg| {
1569 try self.asmRegisterRegister(
1570 tag,
1571 dst_alias,
1572 registerAlias(src_reg, min_abi_size),
1573 );
1574 },
1575 .stack_offset => |src_off| {
1576 try self.asmRegisterMemory(tag, dst_alias, Memory.sib(
1577 Memory.PtrSize.fromSize(min_abi_size),
1578 .{ .base = .rbp, .disp = -src_off },
1579 ));
1580 },
1581 else => return self.fail("TODO airIntCast from {s} to {s}", .{
1582 @tagName(src_mcv),
1583 @tagName(dst_mcv),
1584 }),
1585 }
1586 if (self.regExtraBits(min_ty) > 0) try self.truncateRegister(min_ty, dst_reg);
1587 },
1588 else => {
1589 try self.setRegOrMem(min_ty, dst_mcv, src_mcv);
1590 const extra = dst_abi_size * 8 - dst_int_info.bits;
1591 if (extra > 0) {
1592 try self.genShiftBinOpMir(switch (signedness) {
1593 .signed => .sal,
1594 .unsigned => .shl,
1595 }, dst_ty, dst_mcv, .{ .immediate = extra });
1596 try self.genShiftBinOpMir(switch (signedness) {
1597 .signed => .sar,
1598 .unsigned => .shr,
1599 }, dst_ty, dst_mcv, .{ .immediate = extra });
1600 }
1601 },
1602 }
1603 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
1617}1604}
16181605
1619fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {1606fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1620 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1607 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1621 const result = if (self.liveness.isUnused(inst)) .unreach else result: {
1622 const dst_ty = self.air.typeOfIndex(inst);
1623 const dst_abi_size = dst_ty.abiSize(self.target.*);
1624 if (dst_abi_size > 8) {
1625 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});
1626 }
1627
1628 const src_mcv = try self.resolveInst(ty_op.operand);
1629 const src_lock = switch (src_mcv) {
1630 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1631 else => null,
1632 };
1633 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
16341608
1635 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))1609 const dst_ty = self.air.typeOfIndex(inst);
1636 src_mcv1610 const dst_abi_size = dst_ty.abiSize(self.target.*);
1637 else1611 if (dst_abi_size > 8) {
1638 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);1612 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});
1613 }
16391614
1640 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result1615 const src_mcv = try self.resolveInst(ty_op.operand);
1641 // have to be removed. this only happens if the dst if not a power-of-two size.1616 const src_lock = switch (src_mcv) {
1642 if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64());1617 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1643 break :result dst_mcv;1618 else => null,
1644 };1619 };
1645 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1620 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1621
1622 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
1623 src_mcv
1624 else
1625 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
1626
1627 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result
1628 // have to be removed. this only happens if the dst if not a power-of-two size.
1629 if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64());
1630
1631 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
1646}1632}
16471633
1648fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {1634fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
1649 const un_op = self.air.instructions.items(.data)[inst].un_op;1635 const un_op = self.air.instructions.items(.data)[inst].un_op;
1636 const ty = self.air.typeOfIndex(inst);
1637
1650 const operand = try self.resolveInst(un_op);1638 const operand = try self.resolveInst(un_op);
1651 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else operand;1639 const dst_mcv = if (self.reuseOperand(inst, un_op, 0, operand))
1652 return self.finishAir(inst, result, .{ un_op, .none, .none });1640 operand
1641 else
1642 try self.copyToRegisterWithInstTracking(inst, ty, operand);
1643
1644 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
1653}1645}
16541646
1655fn airSlice(self: *Self, inst: Air.Inst.Index) !void {1647fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1656 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1648 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1657 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1649 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
16581650
1659 if (self.liveness.isUnused(inst)) {
1660 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
1661 }
1662
1663 const ptr = try self.resolveInst(bin_op.lhs);1651 const ptr = try self.resolveInst(bin_op.lhs);
1664 const ptr_ty = self.air.typeOf(bin_op.lhs);1652 const ptr_ty = self.air.typeOf(bin_op.lhs);
1665 const len = try self.resolveInst(bin_op.rhs);1653 const len = try self.resolveInst(bin_op.rhs);
...@@ -1675,33 +1663,21 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1675,33 +1663,21 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
16751663
1676fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1664fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1677 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1665 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
16781666 const dst_mcv = try self.genUnOp(inst, tag, ty_op.operand);
1679 const result = if (self.liveness.isUnused(inst))1667 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
1680 .unreach
1681 else
1682 try self.genUnOp(inst, tag, ty_op.operand);
1683 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1684}1668}
16851669
1686fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1670fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1687 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1671 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
16881672 const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
1689 const result = if (self.liveness.isUnused(inst))1673 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1690 .unreach
1691 else
1692 try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
1693 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1694}1674}
16951675
1696fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1676fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1697 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1677 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1698 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1678 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
16991679 const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
1700 const result = if (self.liveness.isUnused(inst))1680 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1701 .unreach
1702 else
1703 try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
1704 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1705}1681}
17061682
1707fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {1683fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
...@@ -1741,7 +1717,7 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {...@@ -1741,7 +1717,7 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
17411717
1742fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {1718fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
1743 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1719 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1744 const result = if (self.liveness.isUnused(inst)) .unreach else result: {1720 const result = result: {
1745 const tag = self.air.instructions.items(.tag)[inst];1721 const tag = self.air.instructions.items(.tag)[inst];
1746 const dst_ty = self.air.typeOfIndex(inst);1722 const dst_ty = self.air.typeOfIndex(inst);
1747 if (dst_ty.zigTypeTag() == .Float)1723 if (dst_ty.zigTypeTag() == .Float)
...@@ -1772,168 +1748,162 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -1772,168 +1748,162 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
17721748
1773fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {1749fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
1774 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1750 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1775 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1751 const ty = self.air.typeOf(bin_op.lhs);
1776 const ty = self.air.typeOf(bin_op.lhs);
17771752
1778 const lhs_mcv = try self.resolveInst(bin_op.lhs);1753 const lhs_mcv = try self.resolveInst(bin_op.lhs);
1779 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))1754 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
1780 lhs_mcv1755 lhs_mcv
1781 else1756 else
1782 try self.copyToRegisterWithInstTracking(inst, ty, lhs_mcv);1757 try self.copyToRegisterWithInstTracking(inst, ty, lhs_mcv);
1783 const dst_reg = dst_mcv.register;1758 const dst_reg = dst_mcv.register;
1784 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);1759 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
1785 defer self.register_manager.unlockReg(dst_lock);1760 defer self.register_manager.unlockReg(dst_lock);
17861761
1787 const rhs_mcv = try self.resolveInst(bin_op.rhs);1762 const rhs_mcv = try self.resolveInst(bin_op.rhs);
1788 const rhs_lock = switch (rhs_mcv) {1763 const rhs_lock = switch (rhs_mcv) {
1789 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),1764 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1790 else => null,1765 else => null,
1791 };1766 };
1792 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);1767 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1793
1794 const limit_reg = try self.register_manager.allocReg(null, gp);
1795 const limit_mcv = MCValue{ .register = limit_reg };
1796 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1797 defer self.register_manager.unlockReg(limit_lock);
1798
1799 const reg_bits = self.regBitSize(ty);
1800 const cc: Condition = if (ty.isSignedInt()) cc: {
1801 try self.genSetReg(ty, limit_reg, dst_mcv);
1802 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1803 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1804 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1805 });
1806 break :cc .o;
1807 } else cc: {
1808 try self.genSetReg(ty, limit_reg, .{
1809 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - reg_bits),
1810 });
1811 break :cc .c;
1812 };
1813 try self.genBinOpMir(.add, ty, dst_mcv, rhs_mcv);
18141768
1815 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);1769 const limit_reg = try self.register_manager.allocReg(null, gp);
1816 try self.asmCmovccRegisterRegister(1770 const limit_mcv = MCValue{ .register = limit_reg };
1817 registerAlias(dst_reg, cmov_abi_size),1771 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1818 registerAlias(limit_reg, cmov_abi_size),1772 defer self.register_manager.unlockReg(limit_lock);
1819 cc,1773
1820 );1774 const reg_bits = self.regBitSize(ty);
1821 break :result dst_mcv;1775 const cc: Condition = if (ty.isSignedInt()) cc: {
1776 try self.genSetReg(ty, limit_reg, dst_mcv);
1777 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1778 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1779 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1780 });
1781 break :cc .o;
1782 } else cc: {
1783 try self.genSetReg(ty, limit_reg, .{
1784 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - reg_bits),
1785 });
1786 break :cc .c;
1822 };1787 };
1823 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1788 try self.genBinOpMir(.add, ty, dst_mcv, rhs_mcv);
1789
1790 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
1791 try self.asmCmovccRegisterRegister(
1792 registerAlias(dst_reg, cmov_abi_size),
1793 registerAlias(limit_reg, cmov_abi_size),
1794 cc,
1795 );
1796
1797 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1824}1798}
18251799
1826fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {1800fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
1827 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1801 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1828 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1802 const ty = self.air.typeOf(bin_op.lhs);
1829 const ty = self.air.typeOf(bin_op.lhs);
1830
1831 const lhs_mcv = try self.resolveInst(bin_op.lhs);
1832 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
1833 lhs_mcv
1834 else
1835 try self.copyToRegisterWithInstTracking(inst, ty, lhs_mcv);
1836 const dst_reg = dst_mcv.register;
1837 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
1838 defer self.register_manager.unlockReg(dst_lock);
18391803
1840 const rhs_mcv = try self.resolveInst(bin_op.rhs);1804 const lhs_mcv = try self.resolveInst(bin_op.lhs);
1841 const rhs_lock = switch (rhs_mcv) {1805 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
1842 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),1806 lhs_mcv
1843 else => null,1807 else
1844 };1808 try self.copyToRegisterWithInstTracking(inst, ty, lhs_mcv);
1845 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);1809 const dst_reg = dst_mcv.register;
18461810 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
1847 const limit_reg = try self.register_manager.allocReg(null, gp);1811 defer self.register_manager.unlockReg(dst_lock);
1848 const limit_mcv = MCValue{ .register = limit_reg };
1849 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1850 defer self.register_manager.unlockReg(limit_lock);
1851
1852 const reg_bits = self.regBitSize(ty);
1853 const cc: Condition = if (ty.isSignedInt()) cc: {
1854 try self.genSetReg(ty, limit_reg, dst_mcv);
1855 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1856 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1857 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1858 });
1859 break :cc .o;
1860 } else cc: {
1861 try self.genSetReg(ty, limit_reg, .{ .immediate = 0 });
1862 break :cc .c;
1863 };
1864 try self.genBinOpMir(.sub, ty, dst_mcv, rhs_mcv);
18651812
1866 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);1813 const rhs_mcv = try self.resolveInst(bin_op.rhs);
1867 try self.asmCmovccRegisterRegister(1814 const rhs_lock = switch (rhs_mcv) {
1868 registerAlias(dst_reg, cmov_abi_size),1815 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1869 registerAlias(limit_reg, cmov_abi_size),1816 else => null,
1870 cc,
1871 );
1872 break :result dst_mcv;
1873 };1817 };
1874 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1818 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1819
1820 const limit_reg = try self.register_manager.allocReg(null, gp);
1821 const limit_mcv = MCValue{ .register = limit_reg };
1822 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1823 defer self.register_manager.unlockReg(limit_lock);
1824
1825 const reg_bits = self.regBitSize(ty);
1826 const cc: Condition = if (ty.isSignedInt()) cc: {
1827 try self.genSetReg(ty, limit_reg, dst_mcv);
1828 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1829 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1830 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1831 });
1832 break :cc .o;
1833 } else cc: {
1834 try self.genSetReg(ty, limit_reg, .{ .immediate = 0 });
1835 break :cc .c;
1836 };
1837 try self.genBinOpMir(.sub, ty, dst_mcv, rhs_mcv);
1838
1839 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
1840 try self.asmCmovccRegisterRegister(
1841 registerAlias(dst_reg, cmov_abi_size),
1842 registerAlias(limit_reg, cmov_abi_size),
1843 cc,
1844 );
1845
1846 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1875}1847}
18761848
1877fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {1849fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
1878 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1850 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1879 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1851 const ty = self.air.typeOf(bin_op.lhs);
1880 const ty = self.air.typeOf(bin_op.lhs);
18811852
1882 try self.spillRegisters(&.{ .rax, .rdx });1853 try self.spillRegisters(&.{ .rax, .rdx });
1883 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });1854 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
1884 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);1855 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
18851856
1886 const lhs_mcv = try self.resolveInst(bin_op.lhs);1857 const lhs_mcv = try self.resolveInst(bin_op.lhs);
1887 const lhs_lock = switch (lhs_mcv) {1858 const lhs_lock = switch (lhs_mcv) {
1888 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),1859 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1889 else => null,1860 else => null,
1890 };1861 };
1891 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);1862 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
18921863
1893 const rhs_mcv = try self.resolveInst(bin_op.rhs);1864 const rhs_mcv = try self.resolveInst(bin_op.rhs);
1894 const rhs_lock = switch (rhs_mcv) {1865 const rhs_lock = switch (rhs_mcv) {
1895 .register => |reg| self.register_manager.lockReg(reg),1866 .register => |reg| self.register_manager.lockReg(reg),
1896 else => null,1867 else => null,
1897 };1868 };
1898 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);1869 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1899
1900 const limit_reg = try self.register_manager.allocReg(null, gp);
1901 const limit_mcv = MCValue{ .register = limit_reg };
1902 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1903 defer self.register_manager.unlockReg(limit_lock);
1904
1905 const reg_bits = self.regBitSize(ty);
1906 const cc: Condition = if (ty.isSignedInt()) cc: {
1907 try self.genSetReg(ty, limit_reg, lhs_mcv);
1908 try self.genBinOpMir(.xor, ty, limit_mcv, rhs_mcv);
1909 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1910 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1911 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1912 });
1913 break :cc .o;
1914 } else cc: {
1915 try self.genSetReg(ty, limit_reg, .{
1916 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - reg_bits),
1917 });
1918 break :cc .c;
1919 };
19201870
1921 const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv);1871 const limit_reg = try self.register_manager.allocReg(null, gp);
1922 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);1872 const limit_mcv = MCValue{ .register = limit_reg };
1923 try self.asmCmovccRegisterRegister(1873 const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg);
1924 registerAlias(dst_mcv.register, cmov_abi_size),1874 defer self.register_manager.unlockReg(limit_lock);
1925 registerAlias(limit_reg, cmov_abi_size),1875
1926 cc,1876 const reg_bits = self.regBitSize(ty);
1927 );1877 const cc: Condition = if (ty.isSignedInt()) cc: {
1928 break :result dst_mcv;1878 try self.genSetReg(ty, limit_reg, lhs_mcv);
1879 try self.genBinOpMir(.xor, ty, limit_mcv, rhs_mcv);
1880 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
1881 try self.genBinOpMir(.xor, ty, limit_mcv, .{
1882 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
1883 });
1884 break :cc .o;
1885 } else cc: {
1886 try self.genSetReg(ty, limit_reg, .{
1887 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - reg_bits),
1888 });
1889 break :cc .c;
1929 };1890 };
1930 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1891
1892 const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv);
1893 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
1894 try self.asmCmovccRegisterRegister(
1895 registerAlias(dst_mcv.register, cmov_abi_size),
1896 registerAlias(limit_reg, cmov_abi_size),
1897 cc,
1898 );
1899
1900 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1931}1901}
19321902
1933fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {1903fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1934 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1904 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1935 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1905 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1936 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1906 const result: MCValue = result: {
1937 const tag = self.air.instructions.items(.tag)[inst];1907 const tag = self.air.instructions.items(.tag)[inst];
1938 const ty = self.air.typeOf(bin_op.lhs);1908 const ty = self.air.typeOf(bin_op.lhs);
1939 switch (ty.zigTypeTag()) {1909 switch (ty.zigTypeTag()) {
...@@ -1992,7 +1962,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1992,7 +1962,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1992fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {1962fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1993 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1963 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1994 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1964 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1995 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1965 const result: MCValue = result: {
1996 const lhs_ty = self.air.typeOf(bin_op.lhs);1966 const lhs_ty = self.air.typeOf(bin_op.lhs);
1997 const rhs_ty = self.air.typeOf(bin_op.rhs);1967 const rhs_ty = self.air.typeOf(bin_op.rhs);
1998 switch (lhs_ty.zigTypeTag()) {1968 switch (lhs_ty.zigTypeTag()) {
...@@ -2114,7 +2084,7 @@ fn genSetStackTruncatedOverflowCompare(...@@ -2114,7 +2084,7 @@ fn genSetStackTruncatedOverflowCompare(
2114fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2084fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2115 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2085 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2116 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2086 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2117 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2087 const result: MCValue = result: {
2118 const dst_ty = self.air.typeOf(bin_op.lhs);2088 const dst_ty = self.air.typeOf(bin_op.lhs);
2119 switch (dst_ty.zigTypeTag()) {2089 switch (dst_ty.zigTypeTag()) {
2120 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),2090 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),
...@@ -2303,10 +2273,6 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -2303,10 +2273,6 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
2303fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {2273fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
2304 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2274 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
23052275
2306 if (self.liveness.isUnused(inst)) {
2307 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
2308 }
2309
2310 try self.spillRegisters(&.{.rcx});2276 try self.spillRegisters(&.{.rcx});
23112277
2312 const tag = self.air.instructions.items(.tag)[inst];2278 const tag = self.air.instructions.items(.tag)[inst];
...@@ -2323,18 +2289,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -2323,18 +2289,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
23232289
2324fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {2290fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2325 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2291 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2326 const result: MCValue = if (self.liveness.isUnused(inst))2292 _ = bin_op;
2327 .unreach2293 return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
2328 else2294 //return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2329 return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
2330 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2331}2295}
23322296
2333fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {2297fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
2334 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2298 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2335 const result: MCValue = result: {2299 const result: MCValue = result: {
2336 if (self.liveness.isUnused(inst)) break :result .unreach;
2337
2338 const pl_ty = self.air.typeOfIndex(inst);2300 const pl_ty = self.air.typeOfIndex(inst);
2339 const opt_mcv = try self.resolveInst(ty_op.operand);2301 const opt_mcv = try self.resolveInst(ty_op.operand);
23402302
...@@ -2359,18 +2321,15 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2359,18 +2321,15 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
23592321
2360fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2322fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
2361 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2323 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2362 const result: MCValue = result: {
2363 if (self.liveness.isUnused(inst)) break :result .unreach;
23642324
2365 const dst_ty = self.air.typeOfIndex(inst);2325 const dst_ty = self.air.typeOfIndex(inst);
2366 const opt_mcv = try self.resolveInst(ty_op.operand);2326 const opt_mcv = try self.resolveInst(ty_op.operand);
23672327
2368 break :result if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))2328 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))
2369 opt_mcv2329 opt_mcv
2370 else2330 else
2371 try self.copyToRegisterWithInstTracking(inst, dst_ty, opt_mcv);2331 try self.copyToRegisterWithInstTracking(inst, dst_ty, opt_mcv);
2372 };2332 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2373 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2374}2333}
23752334
2376fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {2335fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2409,9 +2368,6 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -2409,9 +2368,6 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
24092368
2410fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {2369fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2411 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2370 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2412 if (self.liveness.isUnused(inst)) {
2413 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
2414 }
2415 const err_union_ty = self.air.typeOf(ty_op.operand);2371 const err_union_ty = self.air.typeOf(ty_op.operand);
2416 const err_ty = err_union_ty.errorUnionSet();2372 const err_ty = err_union_ty.errorUnionSet();
2417 const payload_ty = err_union_ty.errorUnionPayload();2373 const payload_ty = err_union_ty.errorUnionPayload();
...@@ -2454,9 +2410,6 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2454,9 +2410,6 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
24542410
2455fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {2411fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2456 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2412 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2457 if (self.liveness.isUnused(inst)) {
2458 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
2459 }
2460 const err_union_ty = self.air.typeOf(ty_op.operand);2413 const err_union_ty = self.air.typeOf(ty_op.operand);
2461 const operand = try self.resolveInst(ty_op.operand);2414 const operand = try self.resolveInst(ty_op.operand);
2462 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);2415 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);
...@@ -2507,72 +2460,68 @@ fn genUnwrapErrorUnionPayloadMir(...@@ -2507,72 +2460,68 @@ fn genUnwrapErrorUnionPayloadMir(
2507// *(E!T) -> E2460// *(E!T) -> E
2508fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {2461fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
2509 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2462 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2510 const result: MCValue = result: {
2511 if (self.liveness.isUnused(inst)) break :result .unreach;
25122463
2513 const src_ty = self.air.typeOf(ty_op.operand);2464 const src_ty = self.air.typeOf(ty_op.operand);
2514 const src_mcv = try self.resolveInst(ty_op.operand);2465 const src_mcv = try self.resolveInst(ty_op.operand);
2515 const src_reg = switch (src_mcv) {2466 const src_reg = switch (src_mcv) {
2516 .register => |reg| reg,2467 .register => |reg| reg,
2517 else => try self.copyToTmpRegister(src_ty, src_mcv),2468 else => try self.copyToTmpRegister(src_ty, src_mcv),
2518 };2469 };
2519 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);2470 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2520 defer self.register_manager.unlockReg(src_lock);2471 defer self.register_manager.unlockReg(src_lock);
25212472
2522 const dst_reg = try self.register_manager.allocReg(inst, gp);2473 const dst_reg = try self.register_manager.allocReg(inst, gp);
2523 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);2474 const dst_mcv = MCValue{ .register = dst_reg };
2524 defer self.register_manager.unlockReg(dst_lock);2475 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
2476 defer self.register_manager.unlockReg(dst_lock);
25252477
2526 const eu_ty = src_ty.childType();2478 const eu_ty = src_ty.childType();
2527 const pl_ty = eu_ty.errorUnionPayload();2479 const pl_ty = eu_ty.errorUnionPayload();
2528 const err_ty = eu_ty.errorUnionSet();2480 const err_ty = eu_ty.errorUnionSet();
2529 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));2481 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
2530 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));2482 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
2531 try self.asmRegisterMemory(2483 try self.asmRegisterMemory(
2532 .mov,2484 .mov,
2533 registerAlias(dst_reg, err_abi_size),2485 registerAlias(dst_reg, err_abi_size),
2534 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ .base = src_reg, .disp = err_off }),2486 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ .base = src_reg, .disp = err_off }),
2535 );2487 );
2536 break :result .{ .register = dst_reg };2488
2537 };2489 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2538 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2539}2490}
25402491
2541// *(E!T) -> *T2492// *(E!T) -> *T
2542fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2493fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
2543 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2494 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2544 const result: MCValue = result: {
2545 if (self.liveness.isUnused(inst)) break :result .unreach;
25462495
2547 const src_ty = self.air.typeOf(ty_op.operand);2496 const src_ty = self.air.typeOf(ty_op.operand);
2548 const src_mcv = try self.resolveInst(ty_op.operand);2497 const src_mcv = try self.resolveInst(ty_op.operand);
2549 const src_reg = switch (src_mcv) {2498 const src_reg = switch (src_mcv) {
2550 .register => |reg| reg,2499 .register => |reg| reg,
2551 else => try self.copyToTmpRegister(src_ty, src_mcv),2500 else => try self.copyToTmpRegister(src_ty, src_mcv),
2552 };2501 };
2553 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);2502 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2554 defer self.register_manager.unlockReg(src_lock);2503 defer self.register_manager.unlockReg(src_lock);
25552504
2556 const dst_ty = self.air.typeOfIndex(inst);2505 const dst_ty = self.air.typeOfIndex(inst);
2557 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))2506 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2558 src_reg2507 src_reg
2559 else2508 else
2560 try self.register_manager.allocReg(inst, gp);2509 try self.register_manager.allocReg(inst, gp);
2561 const dst_lock = self.register_manager.lockReg(dst_reg);2510 const dst_mcv = MCValue{ .register = dst_reg };
2562 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);2511 const dst_lock = self.register_manager.lockReg(dst_reg);
2512 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
25632513
2564 const eu_ty = src_ty.childType();2514 const eu_ty = src_ty.childType();
2565 const pl_ty = eu_ty.errorUnionPayload();2515 const pl_ty = eu_ty.errorUnionPayload();
2566 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));2516 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
2567 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));2517 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2568 try self.asmRegisterMemory(2518 try self.asmRegisterMemory(
2569 .lea,2519 .lea,
2570 registerAlias(dst_reg, dst_abi_size),2520 registerAlias(dst_reg, dst_abi_size),
2571 Memory.sib(.qword, .{ .base = src_reg, .disp = pl_off }),2521 Memory.sib(.qword, .{ .base = src_reg, .disp = pl_off }),
2572 );2522 );
2573 break :result .{ .register = dst_reg };2523
2574 };2524 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2575 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2576}2525}
25772526
2578fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {2527fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2621,11 +2570,9 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -2621,11 +2570,9 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
2621}2570}
26222571
2623fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {2572fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
2624 const result: MCValue = if (self.liveness.isUnused(inst))2573 _ = inst;
2625 .unreach2574 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});
2626 else2575 //return self.finishAir(inst, result, .{ .none, .none, .none });
2627 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});
2628 return self.finishAir(inst, result, .{ .none, .none, .none });
2629}2576}
26302577
2631fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {2578fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2641,8 +2588,6 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {...@@ -2641,8 +2588,6 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
2641fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {2588fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2642 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2589 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2643 const result: MCValue = result: {2590 const result: MCValue = result: {
2644 if (self.liveness.isUnused(inst)) break :result .unreach;
2645
2646 const pl_ty = self.air.typeOf(ty_op.operand);2591 const pl_ty = self.air.typeOf(ty_op.operand);
2647 if (!pl_ty.hasRuntimeBits()) break :result .{ .immediate = 1 };2592 if (!pl_ty.hasRuntimeBits()) break :result .{ .immediate = 1 };
26482593
...@@ -2687,10 +2632,6 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -2687,10 +2632,6 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2687fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {2632fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2688 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2633 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
26892634
2690 if (self.liveness.isUnused(inst)) {
2691 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
2692 }
2693
2694 const error_union_ty = self.air.getRefType(ty_op.ty);2635 const error_union_ty = self.air.getRefType(ty_op.ty);
2695 const payload_ty = error_union_ty.errorUnionPayload();2636 const payload_ty = error_union_ty.errorUnionPayload();
2696 const operand = try self.resolveInst(ty_op.operand);2637 const operand = try self.resolveInst(ty_op.operand);
...@@ -2717,9 +2658,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2717,9 +2658,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2717/// E to E!T2658/// E to E!T
2718fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {2659fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2719 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2660 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2720 if (self.liveness.isUnused(inst)) {2661
2721 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
2722 }
2723 const error_union_ty = self.air.getRefType(ty_op.ty);2662 const error_union_ty = self.air.getRefType(ty_op.ty);
2724 const payload_ty = error_union_ty.errorUnionPayload();2663 const payload_ty = error_union_ty.errorUnionPayload();
2725 const operand = try self.resolveInst(ty_op.operand);2664 const operand = try self.resolveInst(ty_op.operand);
...@@ -2745,7 +2684,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2745,7 +2684,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
27452684
2746fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {2685fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
2747 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2686 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2748 const result = if (self.liveness.isUnused(inst)) .unreach else result: {2687 const result = result: {
2749 const src_mcv = try self.resolveInst(ty_op.operand);2688 const src_mcv = try self.resolveInst(ty_op.operand);
2750 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;2689 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
27512690
...@@ -2759,72 +2698,65 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2759,72 +2698,65 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
27592698
2760fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {2699fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
2761 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2700 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2762 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2701
2763 const operand = try self.resolveInst(ty_op.operand);2702 const operand = try self.resolveInst(ty_op.operand);
2764 const dst_mcv: MCValue = blk: {2703 const dst_mcv: MCValue = blk: {
2765 switch (operand) {2704 switch (operand) {
2766 .stack_offset => |off| {2705 .stack_offset => |off| {
2767 break :blk MCValue{ .stack_offset = off - 8 };2706 break :blk MCValue{ .stack_offset = off - 8 };
2768 },2707 },
2769 else => return self.fail("TODO implement slice_len for {}", .{operand}),2708 else => return self.fail("TODO implement slice_len for {}", .{operand}),
2770 }2709 }
2771 };
2772 break :result dst_mcv;
2773 };2710 };
2774 log.debug("airSliceLen(%{d}): {}", .{ inst, result });2711
2775 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2712 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2776}2713}
27772714
2778fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {2715fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
2779 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2716 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2780 const result: MCValue = result: {
2781 if (self.liveness.isUnused(inst)) break :result .unreach;
27822717
2783 const src_ty = self.air.typeOf(ty_op.operand);2718 const src_ty = self.air.typeOf(ty_op.operand);
2784 const src_mcv = try self.resolveInst(ty_op.operand);2719 const src_mcv = try self.resolveInst(ty_op.operand);
2785 const src_reg = switch (src_mcv) {2720 const src_reg = switch (src_mcv) {
2786 .register => |reg| reg,2721 .register => |reg| reg,
2787 else => try self.copyToTmpRegister(src_ty, src_mcv),2722 else => try self.copyToTmpRegister(src_ty, src_mcv),
2788 };2723 };
2789 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);2724 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
2790 defer self.register_manager.unlockReg(src_lock);2725 defer self.register_manager.unlockReg(src_lock);
27912726
2792 const dst_ty = self.air.typeOfIndex(inst);2727 const dst_ty = self.air.typeOfIndex(inst);
2793 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))2728 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2794 src_reg2729 src_reg
2795 else2730 else
2796 try self.register_manager.allocReg(inst, gp);2731 try self.register_manager.allocReg(inst, gp);
2797 const dst_lock = self.register_manager.lockReg(dst_reg);2732 const dst_mcv = MCValue{ .register = dst_reg };
2798 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);2733 const dst_lock = self.register_manager.lockReg(dst_reg);
2734 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
27992735
2800 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));2736 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2801 try self.asmRegisterMemory(2737 try self.asmRegisterMemory(
2802 .lea,2738 .lea,
2803 registerAlias(dst_reg, dst_abi_size),2739 registerAlias(dst_reg, dst_abi_size),
2804 Memory.sib(.qword, .{2740 Memory.sib(.qword, .{
2805 .base = src_reg,2741 .base = src_reg,
2806 .disp = @divExact(self.target.cpu.arch.ptrBitWidth(), 8),2742 .disp = @divExact(self.target.cpu.arch.ptrBitWidth(), 8),
2807 }),2743 }),
2808 );2744 );
2809 break :result .{ .register = dst_reg };2745
2810 };2746 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2811 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2812}2747}
28132748
2814fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {2749fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
2815 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2750 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2816 const result: MCValue = result: {
2817 if (self.liveness.isUnused(inst)) break :result .unreach;
28182751
2819 const dst_ty = self.air.typeOfIndex(inst);2752 const dst_ty = self.air.typeOfIndex(inst);
2820 const opt_mcv = try self.resolveInst(ty_op.operand);2753 const opt_mcv = try self.resolveInst(ty_op.operand);
28212754
2822 break :result if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))2755 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))
2823 opt_mcv2756 opt_mcv
2824 else2757 else
2825 try self.copyToRegisterWithInstTracking(inst, dst_ty, opt_mcv);2758 try self.copyToRegisterWithInstTracking(inst, dst_ty, opt_mcv);
2826 };2759 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2827 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2828}2760}
28292761
2830fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {2762fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {
...@@ -2892,34 +2824,26 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -2892,34 +2824,26 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2892fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {2824fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2893 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2825 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2894 const slice_ty = self.air.typeOf(bin_op.lhs);2826 const slice_ty = self.air.typeOf(bin_op.lhs);
2895 const result = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .unreach else result: {2827
2896 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2828 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2897 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);2829 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
2898 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);2830 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
2899 const dst_mcv = try self.allocRegOrMem(inst, false);2831 const dst_mcv = try self.allocRegOrMem(inst, false);
2900 try self.load(dst_mcv, elem_ptr, slice_ptr_field_type);2832 try self.load(dst_mcv, elem_ptr, slice_ptr_field_type);
2901 break :result dst_mcv;2833
2902 };2834 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
2903 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2904}2835}
29052836
2906fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {2837fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2907 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2838 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2908 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2839 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2909 const result: MCValue = if (self.liveness.isUnused(inst))2840 const dst_mcv = try self.genSliceElemPtr(extra.lhs, extra.rhs);
2910 .unreach2841 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
2911 else
2912 try self.genSliceElemPtr(extra.lhs, extra.rhs);
2913 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2914}2842}
29152843
2916fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {2844fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2917 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2845 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
29182846
2919 if (self.liveness.isUnused(inst)) {
2920 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
2921 }
2922
2923 const array_ty = self.air.typeOf(bin_op.lhs);2847 const array_ty = self.air.typeOf(bin_op.lhs);
2924 const array = try self.resolveInst(bin_op.lhs);2848 const array = try self.resolveInst(bin_op.lhs);
2925 const array_lock: ?RegisterLock = switch (array) {2849 const array_lock: ?RegisterLock = switch (array) {
...@@ -2986,77 +2910,74 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2986,77 +2910,74 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2986fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {2910fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2987 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2911 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2988 const ptr_ty = self.air.typeOf(bin_op.lhs);2912 const ptr_ty = self.air.typeOf(bin_op.lhs);
2989 const result = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .unreach else result: {
2990 // this is identical to the `airPtrElemPtr` codegen expect here an
2991 // additional `mov` is needed at the end to get the actual value
2992
2993 const elem_ty = ptr_ty.elemType2();
2994 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2995 const index_ty = self.air.typeOf(bin_op.rhs);
2996 const index_mcv = try self.resolveInst(bin_op.rhs);
2997 const index_lock = switch (index_mcv) {
2998 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2999 else => null,
3000 };
3001 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
30022913
3003 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);2914 // this is identical to the `airPtrElemPtr` codegen expect here an
3004 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2915 // additional `mov` is needed at the end to get the actual value
3005 defer self.register_manager.unlockReg(offset_lock);
30062916
3007 const ptr_mcv = try self.resolveInst(bin_op.lhs);2917 const elem_ty = ptr_ty.elemType2();
3008 const elem_ptr_reg = if (ptr_mcv.isRegister() and self.liveness.operandDies(inst, 0))2918 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
3009 ptr_mcv.register2919 const index_ty = self.air.typeOf(bin_op.rhs);
3010 else2920 const index_mcv = try self.resolveInst(bin_op.rhs);
3011 try self.copyToTmpRegister(ptr_ty, ptr_mcv);2921 const index_lock = switch (index_mcv) {
3012 const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg);2922 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3013 defer self.register_manager.unlockReg(elem_ptr_lock);2923 else => null,
3014 try self.asmRegisterRegister(.add, elem_ptr_reg, offset_reg);2924 };
2925 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
30152926
3016 const dst_mcv = try self.allocRegOrMem(inst, true);2927 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);
3017 const dst_lock = switch (dst_mcv) {2928 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
3018 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2929 defer self.register_manager.unlockReg(offset_lock);
3019 else => null,2930
3020 };2931 const ptr_mcv = try self.resolveInst(bin_op.lhs);
3021 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);2932 const elem_ptr_reg = if (ptr_mcv.isRegister() and self.liveness.operandDies(inst, 0))
3022 try self.load(dst_mcv, .{ .register = elem_ptr_reg }, ptr_ty);2933 ptr_mcv.register
3023 break :result dst_mcv;2934 else
2935 try self.copyToTmpRegister(ptr_ty, ptr_mcv);
2936 const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg);
2937 defer self.register_manager.unlockReg(elem_ptr_lock);
2938 try self.asmRegisterRegister(.add, elem_ptr_reg, offset_reg);
2939
2940 const dst_mcv = try self.allocRegOrMem(inst, true);
2941 const dst_lock = switch (dst_mcv) {
2942 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2943 else => null,
3024 };2944 };
3025 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2945 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2946 try self.load(dst_mcv, .{ .register = elem_ptr_reg }, ptr_ty);
2947
2948 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
3026}2949}
30272950
3028fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {2951fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
3029 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2952 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3030 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2953 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
30312954
3032 const result = if (self.liveness.isUnused(inst)) .unreach else result: {2955 const ptr_ty = self.air.typeOf(extra.lhs);
3033 const ptr_ty = self.air.typeOf(extra.lhs);2956 const ptr = try self.resolveInst(extra.lhs);
3034 const ptr = try self.resolveInst(extra.lhs);2957 const ptr_lock: ?RegisterLock = switch (ptr) {
3035 const ptr_lock: ?RegisterLock = switch (ptr) {2958 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3036 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2959 else => null,
3037 else => null,2960 };
3038 };2961 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
3039 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
30402962
3041 const elem_ty = ptr_ty.elemType2();2963 const elem_ty = ptr_ty.elemType2();
3042 const elem_abi_size = elem_ty.abiSize(self.target.*);2964 const elem_abi_size = elem_ty.abiSize(self.target.*);
3043 const index_ty = self.air.typeOf(extra.rhs);2965 const index_ty = self.air.typeOf(extra.rhs);
3044 const index = try self.resolveInst(extra.rhs);2966 const index = try self.resolveInst(extra.rhs);
3045 const index_lock: ?RegisterLock = switch (index) {2967 const index_lock: ?RegisterLock = switch (index) {
3046 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),2968 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
3047 else => null,2969 else => null,
3048 };2970 };
3049 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);2971 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
2972
2973 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2974 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2975 defer self.register_manager.unlockReg(offset_reg_lock);
30502976
3051 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2977 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
3052 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2978 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
3053 defer self.register_manager.unlockReg(offset_reg_lock);
30542979
3055 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2980 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
3056 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
3057 break :result dst_mcv;
3058 };
3059 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
3060}2981}
30612982
3062fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {2983fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
...@@ -3098,9 +3019,6 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -3098,9 +3019,6 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
30983019
3099fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {3020fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
3100 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3021 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3101 if (self.liveness.isUnused(inst)) {
3102 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
3103 }
31043022
3105 const tag_ty = self.air.typeOfIndex(inst);3023 const tag_ty = self.air.typeOfIndex(inst);
3106 const union_ty = self.air.typeOf(ty_op.operand);3024 const union_ty = self.air.typeOf(ty_op.operand);
...@@ -3152,8 +3070,6 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -3152,8 +3070,6 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
3152fn airClz(self: *Self, inst: Air.Inst.Index) !void {3070fn airClz(self: *Self, inst: Air.Inst.Index) !void {
3153 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3071 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3154 const result = result: {3072 const result = result: {
3155 if (self.liveness.isUnused(inst)) break :result .unreach;
3156
3157 const dst_ty = self.air.typeOfIndex(inst);3073 const dst_ty = self.air.typeOfIndex(inst);
3158 const src_ty = self.air.typeOf(ty_op.operand);3074 const src_ty = self.air.typeOf(ty_op.operand);
31593075
...@@ -3221,8 +3137,6 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -3221,8 +3137,6 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
3221fn airCtz(self: *Self, inst: Air.Inst.Index) !void {3137fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
3222 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3138 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3223 const result = result: {3139 const result = result: {
3224 if (self.liveness.isUnused(inst)) break :result .unreach;
3225
3226 const dst_ty = self.air.typeOfIndex(inst);3140 const dst_ty = self.air.typeOfIndex(inst);
3227 const src_ty = self.air.typeOf(ty_op.operand);3141 const src_ty = self.air.typeOf(ty_op.operand);
3228 const src_bits = src_ty.bitSize(self.target.*);3142 const src_bits = src_ty.bitSize(self.target.*);
...@@ -3279,8 +3193,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -3279,8 +3193,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
3279fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {3193fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
3280 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3194 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3281 const result: MCValue = result: {3195 const result: MCValue = result: {
3282 if (self.liveness.isUnused(inst)) break :result .unreach;
3283
3284 const src_ty = self.air.typeOf(ty_op.operand);3196 const src_ty = self.air.typeOf(ty_op.operand);
3285 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));3197 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
3286 const src_mcv = try self.resolveInst(ty_op.operand);3198 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -3449,148 +3361,138 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m...@@ -3449,148 +3361,138 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
34493361
3450fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {3362fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3451 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3363 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3452 const result = result: {
3453 if (self.liveness.isUnused(inst)) break :result .unreach;
34543364
3455 const src_ty = self.air.typeOf(ty_op.operand);3365 const src_ty = self.air.typeOf(ty_op.operand);
3456 const src_mcv = try self.resolveInst(ty_op.operand);3366 const src_mcv = try self.resolveInst(ty_op.operand);
34573367
3458 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, true);3368 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, true);
3459 switch (self.regExtraBits(src_ty)) {3369 switch (self.regExtraBits(src_ty)) {
3460 0 => {},3370 0 => {},
3461 else => |extra| try self.genBinOpMir(3371 else => |extra| try self.genBinOpMir(
3462 if (src_ty.isSignedInt()) .sar else .shr,3372 if (src_ty.isSignedInt()) .sar else .shr,
3463 src_ty,3373 src_ty,
3464 dst_mcv,3374 dst_mcv,
3465 .{ .immediate = extra },3375 .{ .immediate = extra },
3466 ),3376 ),
3467 }3377 }
3468 break :result dst_mcv;
3469 };
34703378
3471 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3379 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
3472}3380}
34733381
3474fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {3382fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
3475 const ty_op = self.air.instructions.items(.data)[inst].ty_op;3383 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3476 const result = result: {
3477 if (self.liveness.isUnused(inst)) break :result .unreach;
34783384
3479 const src_ty = self.air.typeOf(ty_op.operand);3385 const src_ty = self.air.typeOf(ty_op.operand);
3480 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));3386 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
3481 const src_mcv = try self.resolveInst(ty_op.operand);3387 const src_mcv = try self.resolveInst(ty_op.operand);
34823388
3483 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false);3389 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false);
3484 const dst_reg = dst_mcv.register;3390 const dst_reg = dst_mcv.register;
3485 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);3391 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
3486 defer self.register_manager.unlockReg(dst_lock);3392 defer self.register_manager.unlockReg(dst_lock);
34873393
3488 const tmp_reg = try self.register_manager.allocReg(null, gp);3394 const tmp_reg = try self.register_manager.allocReg(null, gp);
3489 const tmp_lock = self.register_manager.lockReg(tmp_reg);3395 const tmp_lock = self.register_manager.lockReg(tmp_reg);
3490 defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock);3396 defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock);
34913397
3492 {3398 {
3493 const dst = registerAlias(dst_reg, src_abi_size);3399 const dst = registerAlias(dst_reg, src_abi_size);
3494 const tmp = registerAlias(tmp_reg, src_abi_size);3400 const tmp = registerAlias(tmp_reg, src_abi_size);
3495 const imm = if (src_abi_size > 4)3401 const imm = if (src_abi_size > 4)
3496 try self.register_manager.allocReg(null, gp)3402 try self.register_manager.allocReg(null, gp)
3497 else3403 else
3498 undefined;3404 undefined;
34993405
3500 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - src_abi_size * 8);3406 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - src_abi_size * 8);
3501 const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);3407 const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);
3502 const imm_00_11 = Immediate.u(mask / 0b01_01);3408 const imm_00_11 = Immediate.u(mask / 0b01_01);
3503 const imm_0_1 = Immediate.u(mask / 0b1_1);3409 const imm_0_1 = Immediate.u(mask / 0b1_1);
35043410
3505 // dst = temp1 = bswap(operand)3411 // dst = temp1 = bswap(operand)
3506 try self.asmRegisterRegister(.mov, tmp, dst);3412 try self.asmRegisterRegister(.mov, tmp, dst);
3507 // tmp = temp13413 // tmp = temp1
3508 try self.asmRegisterImmediate(.shr, dst, Immediate.u(4));3414 try self.asmRegisterImmediate(.shr, dst, Immediate.u(4));
3509 // dst = temp1 >> 43415 // dst = temp1 >> 4
3510 if (src_abi_size > 4) {3416 if (src_abi_size > 4) {
3511 try self.asmRegisterImmediate(.mov, imm, imm_0000_1111);3417 try self.asmRegisterImmediate(.mov, imm, imm_0000_1111);
3512 try self.asmRegisterRegister(.@"and", tmp, imm);3418 try self.asmRegisterRegister(.@"and", tmp, imm);
3513 try self.asmRegisterRegister(.@"and", dst, imm);3419 try self.asmRegisterRegister(.@"and", dst, imm);
3514 } else {3420 } else {
3515 try self.asmRegisterImmediate(.@"and", tmp, imm_0000_1111);3421 try self.asmRegisterImmediate(.@"and", tmp, imm_0000_1111);
3516 try self.asmRegisterImmediate(.@"and", dst, imm_0000_1111);3422 try self.asmRegisterImmediate(.@"and", dst, imm_0000_1111);
3517 }3423 }
3518 // tmp = temp1 & 0x0F...0F3424 // tmp = temp1 & 0x0F...0F
3519 // dst = (temp1 >> 4) & 0x0F...0F3425 // dst = (temp1 >> 4) & 0x0F...0F
3520 try self.asmRegisterImmediate(.shl, tmp, Immediate.u(4));3426 try self.asmRegisterImmediate(.shl, tmp, Immediate.u(4));
3521 // tmp = (temp1 & 0x0F...0F) << 43427 // tmp = (temp1 & 0x0F...0F) << 4
3522 try self.asmRegisterRegister(.@"or", dst, tmp);3428 try self.asmRegisterRegister(.@"or", dst, tmp);
3523 // dst = temp2 = ((temp1 >> 4) & 0x0F...0F) | ((temp1 & 0x0F...0F) << 4)3429 // dst = temp2 = ((temp1 >> 4) & 0x0F...0F) | ((temp1 & 0x0F...0F) << 4)
3524 try self.asmRegisterRegister(.mov, tmp, dst);3430 try self.asmRegisterRegister(.mov, tmp, dst);
3525 // tmp = temp23431 // tmp = temp2
3526 try self.asmRegisterImmediate(.shr, dst, Immediate.u(2));3432 try self.asmRegisterImmediate(.shr, dst, Immediate.u(2));
3527 // dst = temp2 >> 23433 // dst = temp2 >> 2
3528 if (src_abi_size > 4) {3434 if (src_abi_size > 4) {
3529 try self.asmRegisterImmediate(.mov, imm, imm_00_11);3435 try self.asmRegisterImmediate(.mov, imm, imm_00_11);
3530 try self.asmRegisterRegister(.@"and", tmp, imm);3436 try self.asmRegisterRegister(.@"and", tmp, imm);
3531 try self.asmRegisterRegister(.@"and", dst, imm);3437 try self.asmRegisterRegister(.@"and", dst, imm);
3532 } else {3438 } else {
3533 try self.asmRegisterImmediate(.@"and", tmp, imm_00_11);3439 try self.asmRegisterImmediate(.@"and", tmp, imm_00_11);
3534 try self.asmRegisterImmediate(.@"and", dst, imm_00_11);3440 try self.asmRegisterImmediate(.@"and", dst, imm_00_11);
3535 }
3536 // tmp = temp2 & 0x33...33
3537 // dst = (temp2 >> 2) & 0x33...33
3538 try self.asmRegisterMemory(
3539 .lea,
3540 if (src_abi_size > 4) tmp.to64() else tmp.to32(),
3541 Memory.sib(.qword, .{
3542 .base = dst.to64(),
3543 .scale_index = .{ .index = tmp.to64(), .scale = 1 << 2 },
3544 }),
3545 );
3546 // tmp = temp3 = ((temp2 >> 2) & 0x33...33) + ((temp2 & 0x33...33) << 2)
3547 try self.asmRegisterRegister(.mov, dst, tmp);
3548 // dst = temp3
3549 try self.asmRegisterImmediate(.shr, tmp, Immediate.u(1));
3550 // tmp = temp3 >> 1
3551 if (src_abi_size > 4) {
3552 try self.asmRegisterImmediate(.mov, imm, imm_0_1);
3553 try self.asmRegisterRegister(.@"and", dst, imm);
3554 try self.asmRegisterRegister(.@"and", tmp, imm);
3555 } else {
3556 try self.asmRegisterImmediate(.@"and", dst, imm_0_1);
3557 try self.asmRegisterImmediate(.@"and", tmp, imm_0_1);
3558 }
3559 // dst = temp3 & 0x55...55
3560 // tmp = (temp3 >> 1) & 0x55...55
3561 try self.asmRegisterMemory(
3562 .lea,
3563 if (src_abi_size > 4) dst.to64() else dst.to32(),
3564 Memory.sib(.qword, .{
3565 .base = tmp.to64(),
3566 .scale_index = .{ .index = dst.to64(), .scale = 1 << 1 },
3567 }),
3568 );
3569 // dst = ((temp3 >> 1) & 0x55...55) + ((temp3 & 0x55...55) << 1)
3570 }3441 }
3442 // tmp = temp2 & 0x33...33
3443 // dst = (temp2 >> 2) & 0x33...33
3444 try self.asmRegisterMemory(
3445 .lea,
3446 if (src_abi_size > 4) tmp.to64() else tmp.to32(),
3447 Memory.sib(.qword, .{
3448 .base = dst.to64(),
3449 .scale_index = .{ .index = tmp.to64(), .scale = 1 << 2 },
3450 }),
3451 );
3452 // tmp = temp3 = ((temp2 >> 2) & 0x33...33) + ((temp2 & 0x33...33) << 2)
3453 try self.asmRegisterRegister(.mov, dst, tmp);
3454 // dst = temp3
3455 try self.asmRegisterImmediate(.shr, tmp, Immediate.u(1));
3456 // tmp = temp3 >> 1
3457 if (src_abi_size > 4) {
3458 try self.asmRegisterImmediate(.mov, imm, imm_0_1);
3459 try self.asmRegisterRegister(.@"and", dst, imm);
3460 try self.asmRegisterRegister(.@"and", tmp, imm);
3461 } else {
3462 try self.asmRegisterImmediate(.@"and", dst, imm_0_1);
3463 try self.asmRegisterImmediate(.@"and", tmp, imm_0_1);
3464 }
3465 // dst = temp3 & 0x55...55
3466 // tmp = (temp3 >> 1) & 0x55...55
3467 try self.asmRegisterMemory(
3468 .lea,
3469 if (src_abi_size > 4) dst.to64() else dst.to32(),
3470 Memory.sib(.qword, .{
3471 .base = tmp.to64(),
3472 .scale_index = .{ .index = dst.to64(), .scale = 1 << 1 },
3473 }),
3474 );
3475 // dst = ((temp3 >> 1) & 0x55...55) + ((temp3 & 0x55...55) << 1)
3476 }
35713477
3572 switch (self.regExtraBits(src_ty)) {3478 switch (self.regExtraBits(src_ty)) {
3573 0 => {},3479 0 => {},
3574 else => |extra| try self.genBinOpMir(3480 else => |extra| try self.genBinOpMir(
3575 if (src_ty.isSignedInt()) .sar else .shr,3481 if (src_ty.isSignedInt()) .sar else .shr,
3576 src_ty,3482 src_ty,
3577 dst_mcv,3483 dst_mcv,
3578 .{ .immediate = extra },3484 .{ .immediate = extra },
3579 ),3485 ),
3580 }3486 }
3581 break :result dst_mcv;
3582 };
35833487
3584 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3488 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
3585}3489}
35863490
3587fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {3491fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
3588 const un_op = self.air.instructions.items(.data)[inst].un_op;3492 const un_op = self.air.instructions.items(.data)[inst].un_op;
3589 const result: MCValue = if (self.liveness.isUnused(inst))3493 _ = un_op;
3590 .unreach3494 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
3591 else3495 //return self.finishAir(inst, result, .{ un_op, .none, .none });
3592 return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
3593 return self.finishAir(inst, result, .{ un_op, .none, .none });
3594}3496}
35953497
3596fn reuseOperand(3498fn reuseOperand(
...@@ -3763,9 +3665,6 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3763,9 +3665,6 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
3763 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);3665 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
37643666
3765 const ptr = try self.resolveInst(ty_op.operand);3667 const ptr = try self.resolveInst(ty_op.operand);
3766 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
3767 if (self.liveness.isUnused(inst) and !is_volatile) break :result .unreach;
3768
3769 const dst_mcv: MCValue = if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr))3668 const dst_mcv: MCValue = if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr))
3770 // The MCValue that holds the pointer can be re-used as the value.3669 // The MCValue that holds the pointer can be re-used as the value.
3771 ptr3670 ptr
...@@ -4062,10 +3961,6 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {...@@ -4062,10 +3961,6 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
4062}3961}
40633962
4064fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {3963fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
4065 if (self.liveness.isUnused(inst)) {
4066 return MCValue.unreach;
4067 }
4068
4069 const mcv = try self.resolveInst(operand);3964 const mcv = try self.resolveInst(operand);
4070 const ptr_ty = self.air.typeOf(operand);3965 const ptr_ty = self.air.typeOf(operand);
4071 const container_ty = ptr_ty.childType();3966 const container_ty = ptr_ty.childType();
...@@ -4132,7 +4027,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32...@@ -4132,7 +4027,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
4132fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {4027fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
4133 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4028 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4134 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;4029 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
4135 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4030 const result: MCValue = result: {
4136 const operand = extra.struct_operand;4031 const operand = extra.struct_operand;
4137 const index = extra.field_index;4032 const index = extra.field_index;
41384033
...@@ -4280,11 +4175,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4280,11 +4175,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
42804175
4281fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {4176fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
4282 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4177 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4283 const result: MCValue = if (self.liveness.isUnused(inst))4178 _ = ty_op;
4284 .unreach4179 return self.fail("TODO implement airFieldParentPtr for {}", .{self.target.cpu.arch});
4285 else4180 //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4286 return self.fail("TODO implement airFieldParentPtr for {}", .{self.target.cpu.arch});
4287 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
4288}4181}
42894182
4290fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {4183fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {
...@@ -5503,9 +5396,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -5503,9 +5396,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
5503 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;5396 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
5504 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);5397 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
55055398
5506 const result: MCValue = result: {5399 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
5507 if (self.liveness.isUnused(inst)) break :result .unreach;
5508
5509 const dst_mcv: MCValue = switch (mcv) {5400 const dst_mcv: MCValue = switch (mcv) {
5510 .register => |reg| blk: {5401 .register => |reg| blk: {
5511 self.register_manager.getRegAssumeFree(reg.to64(), inst);5402 self.register_manager.getRegAssumeFree(reg.to64(), inst);
...@@ -5596,23 +5487,17 @@ fn airBreakpoint(self: *Self) !void {...@@ -5596,23 +5487,17 @@ fn airBreakpoint(self: *Self) !void {
5596}5487}
55975488
5598fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {5489fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {
5599 const result = if (self.liveness.isUnused(inst)) .unreach else result: {5490 const dst_mcv = try self.allocRegOrMem(inst, true);
5600 const dst_mcv = try self.allocRegOrMem(inst, true);5491 try self.setRegOrMem(Type.usize, dst_mcv, .{
5601 try self.setRegOrMem(Type.usize, dst_mcv, .{5492 .stack_offset = -@as(i32, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)),
5602 .stack_offset = -@as(i32, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)),5493 });
5603 });5494 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
5604 break :result dst_mcv;
5605 };
5606 return self.finishAir(inst, result, .{ .none, .none, .none });
5607}5495}
56085496
5609fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {5497fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
5610 const result = if (self.liveness.isUnused(inst)) .unreach else result: {5498 const dst_mcv = try self.allocRegOrMem(inst, true);
5611 const dst_mcv = try self.allocRegOrMem(inst, true);5499 try self.setRegOrMem(Type.usize, dst_mcv, .{ .register = .rbp });
5612 try self.setRegOrMem(Type.usize, dst_mcv, .{ .register = .rbp });5500 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
5613 break :result dst_mcv;
5614 };
5615 return self.finishAir(inst, result, .{ .none, .none, .none });
5616}5501}
56175502
5618fn airFence(self: *Self, inst: Air.Inst.Index) !void {5503fn airFence(self: *Self, inst: Air.Inst.Index) !void {
...@@ -5892,60 +5777,58 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -5892,60 +5777,58 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
58925777
5893fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {5778fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
5894 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5779 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5895 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {5780 const ty = self.air.typeOf(bin_op.lhs);
5896 const ty = self.air.typeOf(bin_op.lhs);5781 const ty_abi_size = ty.abiSize(self.target.*);
5897 const ty_abi_size = ty.abiSize(self.target.*);5782 const can_reuse = ty_abi_size <= 8;
5898 const can_reuse = ty_abi_size <= 8;
58995783
5900 try self.spillEflagsIfOccupied();5784 try self.spillEflagsIfOccupied();
5901 self.eflags_inst = inst;5785 self.eflags_inst = inst;
59025786
5903 const lhs_mcv = try self.resolveInst(bin_op.lhs);5787 const lhs_mcv = try self.resolveInst(bin_op.lhs);
5904 const lhs_lock = switch (lhs_mcv) {5788 const lhs_lock = switch (lhs_mcv) {
5905 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),5789 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5906 else => null,5790 else => null,
5907 };5791 };
5908 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);5792 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
59095793
5910 const rhs_mcv = try self.resolveInst(bin_op.rhs);5794 const rhs_mcv = try self.resolveInst(bin_op.rhs);
5911 const rhs_lock = switch (rhs_mcv) {5795 const rhs_lock = switch (rhs_mcv) {
5912 .register => |reg| self.register_manager.lockReg(reg),5796 .register => |reg| self.register_manager.lockReg(reg),
5913 else => null,5797 else => null,
5914 };5798 };
5915 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);5799 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
59165800
5917 const dst_mem_ok = !ty.isRuntimeFloat();5801 const dst_mem_ok = !ty.isRuntimeFloat();
5918 var flipped = false;5802 var flipped = false;
5919 const dst_mcv: MCValue = if (can_reuse and !lhs_mcv.isImmediate() and5803 const dst_mcv: MCValue = if (can_reuse and !lhs_mcv.isImmediate() and
5920 (dst_mem_ok or lhs_mcv.isRegister()) and self.liveness.operandDies(inst, 0))5804 (dst_mem_ok or lhs_mcv.isRegister()) and self.liveness.operandDies(inst, 0))
5921 lhs_mcv5805 lhs_mcv
5922 else if (can_reuse and !rhs_mcv.isImmediate() and5806 else if (can_reuse and !rhs_mcv.isImmediate() and
5923 (dst_mem_ok or rhs_mcv.isRegister()) and self.liveness.operandDies(inst, 1))5807 (dst_mem_ok or rhs_mcv.isRegister()) and self.liveness.operandDies(inst, 1))
5924 dst: {5808 dst: {
5925 flipped = true;5809 flipped = true;
5926 break :dst rhs_mcv;5810 break :dst rhs_mcv;
5927 } else if (dst_mem_ok) dst: {5811 } else if (dst_mem_ok) dst: {
5928 const dst_mcv = try self.allocTempRegOrMem(ty, true);5812 const dst_mcv = try self.allocTempRegOrMem(ty, true);
5929 try self.setRegOrMem(ty, dst_mcv, lhs_mcv);5813 try self.setRegOrMem(ty, dst_mcv, lhs_mcv);
5930 break :dst dst_mcv;5814 break :dst dst_mcv;
5931 } else .{ .register = try self.copyToTmpRegister(ty, lhs_mcv) };5815 } else .{ .register = try self.copyToTmpRegister(ty, lhs_mcv) };
5932 const dst_lock = switch (dst_mcv) {5816 const dst_lock = switch (dst_mcv) {
5933 .register => |reg| self.register_manager.lockReg(reg),5817 .register => |reg| self.register_manager.lockReg(reg),
5934 else => null,5818 else => null,
5935 };5819 };
5936 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);5820 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
59375821
5938 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;5822 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
5939 try self.genBinOpMir(switch (ty.tag()) {5823 try self.genBinOpMir(switch (ty.tag()) {
5940 else => .cmp,5824 else => .cmp,
5941 .f32 => .ucomiss,5825 .f32 => .ucomiss,
5942 .f64 => .ucomisd,5826 .f64 => .ucomisd,
5943 }, ty, dst_mcv, src_mcv);5827 }, ty, dst_mcv, src_mcv);
59445828
5945 const signedness = if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned;5829 const signedness = if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned;
5946 break :result .{5830 const result = MCValue{
5947 .eflags = Condition.fromCompareOperator(signedness, if (flipped) op.reverse() else op),5831 .eflags = Condition.fromCompareOperator(signedness, if (flipped) op.reverse() else op),
5948 };
5949 };5832 };
5950 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });5833 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
5951}5834}
...@@ -5957,56 +5840,55 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {...@@ -5957,56 +5840,55 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
59575840
5958fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {5841fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
5959 const un_op = self.air.instructions.items(.data)[inst].un_op;5842 const un_op = self.air.instructions.items(.data)[inst].un_op;
5960 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
5961 const addr_reg = try self.register_manager.allocReg(null, gp);
5962 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5963 defer self.register_manager.unlockReg(addr_lock);
5964
5965 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
5966 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(
5967 .{ .kind = .const_data, .ty = Type.anyerror },
5968 4, // dword alignment
5969 );
5970 const got_addr = elf_file.getAtom(atom_index).getOffsetTableAddress(elf_file);
5971 try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{
5972 .base = .ds,
5973 .disp = @intCast(i32, got_addr),
5974 }));
5975 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
5976 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(
5977 .{ .kind = .const_data, .ty = Type.anyerror },
5978 4, // dword alignment
5979 );
5980 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
5981 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5982 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
5983 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
5984 .{ .kind = .const_data, .ty = Type.anyerror },
5985 4, // dword alignment
5986 );
5987 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
5988 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5989 } else {
5990 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
5991 }
59925843
5993 try self.spillEflagsIfOccupied();5844 const addr_reg = try self.register_manager.allocReg(null, gp);
5994 self.eflags_inst = inst;5845 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5846 defer self.register_manager.unlockReg(addr_lock);
59955847
5996 const op_ty = self.air.typeOf(un_op);5848 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
5997 const op_abi_size = @intCast(u32, op_ty.abiSize(self.target.*));5849 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(
5998 const op_mcv = try self.resolveInst(un_op);5850 .{ .kind = .const_data, .ty = Type.anyerror },
5999 const dst_reg = switch (op_mcv) {5851 4, // dword alignment
6000 .register => |reg| reg,5852 );
6001 else => try self.copyToTmpRegister(op_ty, op_mcv),5853 const got_addr = elf_file.getAtom(atom_index).getOffsetTableAddress(elf_file);
6002 };5854 try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{
6003 try self.asmRegisterMemory(5855 .base = .ds,
6004 .cmp,5856 .disp = @intCast(i32, got_addr),
6005 registerAlias(dst_reg, op_abi_size),5857 }));
6006 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = addr_reg }),5858 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
5859 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(
5860 .{ .kind = .const_data, .ty = Type.anyerror },
5861 4, // dword alignment
6007 );5862 );
6008 break :result .{ .eflags = .b };5863 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
5864 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5865 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
5866 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
5867 .{ .kind = .const_data, .ty = Type.anyerror },
5868 4, // dword alignment
5869 );
5870 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
5871 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
5872 } else {
5873 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
5874 }
5875
5876 try self.spillEflagsIfOccupied();
5877 self.eflags_inst = inst;
5878
5879 const op_ty = self.air.typeOf(un_op);
5880 const op_abi_size = @intCast(u32, op_ty.abiSize(self.target.*));
5881 const op_mcv = try self.resolveInst(un_op);
5882 const dst_reg = switch (op_mcv) {
5883 .register => |reg| reg,
5884 else => try self.copyToTmpRegister(op_ty, op_mcv),
6009 };5885 };
5886 try self.asmRegisterMemory(
5887 .cmp,
5888 registerAlias(dst_reg, op_abi_size),
5889 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = addr_reg }),
5890 );
5891 const result = MCValue{ .eflags = .b };
6010 return self.finishAir(inst, result, .{ un_op, .none, .none });5892 return self.finishAir(inst, result, .{ un_op, .none, .none });
6011}5893}
60125894
...@@ -6365,67 +6247,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa...@@ -6365,67 +6247,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa
63656247
6366fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {6248fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
6367 const un_op = self.air.instructions.items(.data)[inst].un_op;6249 const un_op = self.air.instructions.items(.data)[inst].un_op;
6368 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6250 const operand = try self.resolveInst(un_op);
6369 const operand = try self.resolveInst(un_op);6251 const ty = self.air.typeOf(un_op);
6370 const ty = self.air.typeOf(un_op);6252 const result = try self.isNull(inst, ty, operand);
6371 break :result try self.isNull(inst, ty, operand);
6372 };
6373 return self.finishAir(inst, result, .{ un_op, .none, .none });6253 return self.finishAir(inst, result, .{ un_op, .none, .none });
6374}6254}
63756255
6376fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {6256fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
6377 const un_op = self.air.instructions.items(.data)[inst].un_op;6257 const un_op = self.air.instructions.items(.data)[inst].un_op;
6378 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6258 const operand = try self.resolveInst(un_op);
6379 const operand = try self.resolveInst(un_op);6259 const ty = self.air.typeOf(un_op);
6380 const ty = self.air.typeOf(un_op);6260 const result = try self.isNullPtr(inst, ty, operand);
6381 break :result try self.isNullPtr(inst, ty, operand);
6382 };
6383 return self.finishAir(inst, result, .{ un_op, .none, .none });6261 return self.finishAir(inst, result, .{ un_op, .none, .none });
6384}6262}
63856263
6386fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {6264fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
6387 const un_op = self.air.instructions.items(.data)[inst].un_op;6265 const un_op = self.air.instructions.items(.data)[inst].un_op;
6388 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6266 const operand = try self.resolveInst(un_op);
6389 const operand = try self.resolveInst(un_op);6267 const ty = self.air.typeOf(un_op);
6390 const ty = self.air.typeOf(un_op);6268 const result = switch (try self.isNull(inst, ty, operand)) {
6391 break :result switch (try self.isNull(inst, ty, operand)) {6269 .eflags => |cc| .{ .eflags = cc.negate() },
6392 .eflags => |cc| .{ .eflags = cc.negate() },6270 else => unreachable,
6393 else => unreachable,
6394 };
6395 };6271 };
6396 return self.finishAir(inst, result, .{ un_op, .none, .none });6272 return self.finishAir(inst, result, .{ un_op, .none, .none });
6397}6273}
63986274
6399fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {6275fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
6400 const un_op = self.air.instructions.items(.data)[inst].un_op;6276 const un_op = self.air.instructions.items(.data)[inst].un_op;
6401 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6277 const operand = try self.resolveInst(un_op);
6402 const operand = try self.resolveInst(un_op);6278 const ty = self.air.typeOf(un_op);
6403 const ty = self.air.typeOf(un_op);6279 const result = switch (try self.isNullPtr(inst, ty, operand)) {
6404 break :result switch (try self.isNullPtr(inst, ty, operand)) {6280 .eflags => |cc| .{ .eflags = cc.negate() },
6405 .eflags => |cc| .{ .eflags = cc.negate() },6281 else => unreachable,
6406 else => unreachable,
6407 };
6408 };6282 };
6409 return self.finishAir(inst, result, .{ un_op, .none, .none });6283 return self.finishAir(inst, result, .{ un_op, .none, .none });
6410}6284}
64116285
6412fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {6286fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
6413 const un_op = self.air.instructions.items(.data)[inst].un_op;6287 const un_op = self.air.instructions.items(.data)[inst].un_op;
6414 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6288 const operand = try self.resolveInst(un_op);
6415 const operand = try self.resolveInst(un_op);6289 const ty = self.air.typeOf(un_op);
6416 const ty = self.air.typeOf(un_op);6290 const result = try self.isErr(inst, ty, operand);
6417 break :result try self.isErr(inst, ty, operand);
6418 };
6419 return self.finishAir(inst, result, .{ un_op, .none, .none });6291 return self.finishAir(inst, result, .{ un_op, .none, .none });
6420}6292}
64216293
6422fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {6294fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
6423 const un_op = self.air.instructions.items(.data)[inst].un_op;6295 const un_op = self.air.instructions.items(.data)[inst].un_op;
64246296
6425 if (self.liveness.isUnused(inst)) {
6426 return self.finishAir(inst, .unreach, .{ un_op, .none, .none });
6427 }
6428
6429 const operand_ptr = try self.resolveInst(un_op);6297 const operand_ptr = try self.resolveInst(un_op);
6430 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {6298 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
6431 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),6299 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -6451,21 +6319,15 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -6451,21 +6319,15 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
64516319
6452fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {6320fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
6453 const un_op = self.air.instructions.items(.data)[inst].un_op;6321 const un_op = self.air.instructions.items(.data)[inst].un_op;
6454 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {6322 const operand = try self.resolveInst(un_op);
6455 const operand = try self.resolveInst(un_op);6323 const ty = self.air.typeOf(un_op);
6456 const ty = self.air.typeOf(un_op);6324 const result = try self.isNonErr(inst, ty, operand);
6457 break :result try self.isNonErr(inst, ty, operand);
6458 };
6459 return self.finishAir(inst, result, .{ un_op, .none, .none });6325 return self.finishAir(inst, result, .{ un_op, .none, .none });
6460}6326}
64616327
6462fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {6328fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
6463 const un_op = self.air.instructions.items(.data)[inst].un_op;6329 const un_op = self.air.instructions.items(.data)[inst].un_op;
64646330
6465 if (self.liveness.isUnused(inst)) {
6466 return self.finishAir(inst, .unreach, .{ un_op, .none, .none });
6467 }
6468
6469 const operand_ptr = try self.resolveInst(un_op);6331 const operand_ptr = try self.resolveInst(un_op);
6470 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {6332 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
6471 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),6333 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
...@@ -6691,7 +6553,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -6691,7 +6553,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
6691fn airAsm(self: *Self, inst: Air.Inst.Index) !void {6553fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
6692 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6554 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6693 const extra = self.air.extraData(Air.Asm, ty_pl.payload);6555 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
6694 const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0;
6695 const clobbers_len = @truncate(u31, extra.data.flags);6556 const clobbers_len = @truncate(u31, extra.data.flags);
6696 var extra_i: usize = extra.end;6557 var extra_i: usize = extra.end;
6697 const outputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]);6558 const outputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]);
...@@ -6700,216 +6561,214 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -6700,216 +6561,214 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
6700 extra_i += inputs.len;6561 extra_i += inputs.len;
67016562
6702 var result: MCValue = .none;6563 var result: MCValue = .none;
6703 if (!is_volatile and self.liveness.isUnused(inst)) result = .unreach else {6564 var args = std.StringArrayHashMap(MCValue).init(self.gpa);
6704 var args = std.StringArrayHashMap(MCValue).init(self.gpa);6565 try args.ensureTotalCapacity(outputs.len + inputs.len + clobbers_len);
6705 try args.ensureTotalCapacity(outputs.len + inputs.len + clobbers_len);6566 defer {
6706 defer {6567 for (args.values()) |arg| switch (arg) {
6707 for (args.values()) |arg| switch (arg) {6568 .register => |reg| self.register_manager.unlockReg(.{ .register = reg }),
6708 .register => |reg| self.register_manager.unlockReg(.{ .register = reg }),6569 else => {},
6709 else => {},6570 };
6710 };6571 args.deinit();
6711 args.deinit();6572 }
6712 }6573
6574 if (outputs.len > 1) {
6575 return self.fail("TODO implement codegen for asm with more than 1 output", .{});
6576 }
67136577
6714 if (outputs.len > 1) {6578 for (outputs) |output| {
6715 return self.fail("TODO implement codegen for asm with more than 1 output", .{});6579 if (output != .none) {
6580 return self.fail("TODO implement codegen for non-expr asm", .{});
6581 }
6582 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
6583 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
6584 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
6585 // This equation accounts for the fact that even if we have exactly 4 bytes
6586 // for the string, we still use the next u32 for the null terminator.
6587 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
6588
6589 const mcv: MCValue = if (mem.eql(u8, constraint, "=r"))
6590 .{ .register = self.register_manager.tryAllocReg(inst, gp) orelse
6591 return self.fail("ran out of registers lowering inline asm", .{}) }
6592 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))
6593 .{ .register = parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
6594 return self.fail("unrecognized register constraint: '{s}'", .{constraint}) }
6595 else
6596 return self.fail("unrecognized constraint: '{s}'", .{constraint});
6597 args.putAssumeCapacity(name, mcv);
6598 switch (mcv) {
6599 .register => |reg| _ = if (RegisterManager.indexOfRegIntoTracked(reg)) |_|
6600 self.register_manager.lockRegAssumeUnused(reg),
6601 else => {},
6716 }6602 }
6603 if (output == .none) result = mcv;
6604 }
67176605
6718 for (outputs) |output| {6606 for (inputs) |input| {
6719 if (output != .none) {6607 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
6720 return self.fail("TODO implement codegen for non-expr asm", .{});6608 const constraint = std.mem.sliceTo(input_bytes, 0);
6721 }6609 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
6722 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);6610 // This equation accounts for the fact that even if we have exactly 4 bytes
6723 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);6611 // for the string, we still use the next u32 for the null terminator.
6724 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);6612 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
6725 // This equation accounts for the fact that even if we have exactly 4 bytes6613
6726 // for the string, we still use the next u32 for the null terminator.6614 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
6727 extra_i += (constraint.len + name.len + (2 + 3)) / 4;6615 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
6728
6729 const mcv: MCValue = if (mem.eql(u8, constraint, "=r"))
6730 .{ .register = self.register_manager.tryAllocReg(inst, gp) orelse
6731 return self.fail("ran out of registers lowering inline asm", .{}) }
6732 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))
6733 .{ .register = parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
6734 return self.fail("unrecognized register constraint: '{s}'", .{constraint}) }
6735 else
6736 return self.fail("unrecognized constraint: '{s}'", .{constraint});
6737 args.putAssumeCapacity(name, mcv);
6738 switch (mcv) {
6739 .register => |reg| _ = if (RegisterManager.indexOfRegIntoTracked(reg)) |_|
6740 self.register_manager.lockRegAssumeUnused(reg),
6741 else => {},
6742 }
6743 if (output == .none) result = mcv;
6744 }6616 }
6617 const reg_name = constraint[1 .. constraint.len - 1];
6618 const reg = parseRegName(reg_name) orelse
6619 return self.fail("unrecognized register: '{s}'", .{reg_name});
67456620
6746 for (inputs) |input| {6621 const arg_mcv = try self.resolveInst(input);
6747 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);6622 try self.register_manager.getReg(reg, null);
6748 const constraint = std.mem.sliceTo(input_bytes, 0);6623 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
6749 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);6624 }
6625
6626 {
6627 var clobber_i: u32 = 0;
6628 while (clobber_i < clobbers_len) : (clobber_i += 1) {
6629 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
6750 // This equation accounts for the fact that even if we have exactly 4 bytes6630 // This equation accounts for the fact that even if we have exactly 4 bytes
6751 // for the string, we still use the next u32 for the null terminator.6631 // for the string, we still use the next u32 for the null terminator.
6752 extra_i += (constraint.len + name.len + (2 + 3)) / 4;6632 extra_i += clobber.len / 4 + 1;
67536633
6754 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {6634 // TODO honor these
6755 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
6756 }
6757 const reg_name = constraint[1 .. constraint.len - 1];
6758 const reg = parseRegName(reg_name) orelse
6759 return self.fail("unrecognized register: '{s}'", .{reg_name});
6760
6761 const arg_mcv = try self.resolveInst(input);
6762 try self.register_manager.getReg(reg, null);
6763 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
6764 }
6765
6766 {
6767 var clobber_i: u32 = 0;
6768 while (clobber_i < clobbers_len) : (clobber_i += 1) {
6769 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
6770 // This equation accounts for the fact that even if we have exactly 4 bytes
6771 // for the string, we still use the next u32 for the null terminator.
6772 extra_i += clobber.len / 4 + 1;
6773
6774 // TODO honor these
6775 }
6776 }6635 }
6636 }
67776637
6778 const asm_source = mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];6638 const asm_source = mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
6779 var line_it = mem.tokenize(u8, asm_source, "\n\r;");6639 var line_it = mem.tokenize(u8, asm_source, "\n\r;");
6780 while (line_it.next()) |line| {6640 while (line_it.next()) |line| {
6781 var mnem_it = mem.tokenize(u8, line, " \t");6641 var mnem_it = mem.tokenize(u8, line, " \t");
6782 const mnem_str = mnem_it.next() orelse continue;6642 const mnem_str = mnem_it.next() orelse continue;
6783 if (mem.startsWith(u8, mnem_str, "#")) continue;6643 if (mem.startsWith(u8, mnem_str, "#")) continue;
67846644
6785 const mnem_size: ?Memory.PtrSize = if (mem.endsWith(u8, mnem_str, "b"))6645 const mnem_size: ?Memory.PtrSize = if (mem.endsWith(u8, mnem_str, "b"))
6786 .byte6646 .byte
6787 else if (mem.endsWith(u8, mnem_str, "w"))6647 else if (mem.endsWith(u8, mnem_str, "w"))
6788 .word6648 .word
6789 else if (mem.endsWith(u8, mnem_str, "l"))6649 else if (mem.endsWith(u8, mnem_str, "l"))
6790 .dword6650 .dword
6791 else if (mem.endsWith(u8, mnem_str, "q"))6651 else if (mem.endsWith(u8, mnem_str, "q"))
6792 .qword6652 .qword
6793 else6653 else
6794 null;6654 null;
6795 const mnem = std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse6655 const mnem = std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse
6796 (if (mnem_size) |_|6656 (if (mnem_size) |_|
6797 std.meta.stringToEnum(Mir.Inst.Tag, mnem_str[0 .. mnem_str.len - 1])6657 std.meta.stringToEnum(Mir.Inst.Tag, mnem_str[0 .. mnem_str.len - 1])
6798 else6658 else
6799 null) orelse return self.fail("Invalid mnemonic: '{s}'", .{mnem_str});6659 null) orelse return self.fail("Invalid mnemonic: '{s}'", .{mnem_str});
68006660
6801 var op_it = mem.tokenize(u8, mnem_it.rest(), ",");6661 var op_it = mem.tokenize(u8, mnem_it.rest(), ",");
6802 var ops = [1]encoder.Instruction.Operand{.none} ** 4;6662 var ops = [1]encoder.Instruction.Operand{.none} ** 4;
6803 for (&ops) |*op| {6663 for (&ops) |*op| {
6804 const op_str = mem.trim(u8, op_it.next() orelse break, " \t");6664 const op_str = mem.trim(u8, op_it.next() orelse break, " \t");
6805 if (mem.startsWith(u8, op_str, "#")) break;6665 if (mem.startsWith(u8, op_str, "#")) break;
6806 if (mem.startsWith(u8, op_str, "%%")) {6666 if (mem.startsWith(u8, op_str, "%%")) {
6807 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');6667 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
6808 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse6668 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
6809 return self.fail("Invalid register: '{s}'", .{op_str});6669 return self.fail("Invalid register: '{s}'", .{op_str});
6810 if (colon) |colon_pos| {6670 if (colon) |colon_pos| {
6811 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch6671 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch
6812 return self.fail("Invalid displacement: '{s}'", .{op_str});6672 return self.fail("Invalid displacement: '{s}'", .{op_str});
6813 op.* = .{ .mem = Memory.sib(6673 op.* = .{ .mem = Memory.sib(
6814 mnem_size orelse return self.fail("Unknown size: '{s}'", .{op_str}),6674 mnem_size orelse return self.fail("Unknown size: '{s}'", .{op_str}),
6815 .{ .base = reg, .disp = disp },6675 .{ .base = reg, .disp = disp },
6816 ) };6676 ) };
6817 } else {6677 } else {
6818 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())6678 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())
6819 return self.fail("Invalid register size: '{s}'", .{op_str});6679 return self.fail("Invalid register size: '{s}'", .{op_str});
6820 op.* = .{ .reg = reg };6680 op.* = .{ .reg = reg };
6681 }
6682 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
6683 switch (args.get(op_str["%[".len .. op_str.len - "]".len]) orelse
6684 return self.fail("No matching constraint: '{s}'", .{op_str})) {
6685 .register => |reg| op.* = .{ .reg = reg },
6686 else => return self.fail("Invalid constraint: '{s}'", .{op_str}),
6687 }
6688 } else if (mem.startsWith(u8, op_str, "$")) {
6689 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
6690 if (mnem_size) |size| {
6691 const max = @as(u64, math.maxInt(u64)) >>
6692 @intCast(u6, 64 - (size.bitSize() - 1));
6693 if ((if (s < 0) ~s else s) > max)
6694 return self.fail("Invalid immediate size: '{s}'", .{op_str});
6821 }6695 }
6822 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {6696 op.* = .{ .imm = Immediate.s(s) };
6823 switch (args.get(op_str["%[".len .. op_str.len - "]".len]) orelse6697 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
6824 return self.fail("No matching constraint: '{s}'", .{op_str})) {6698 if (mnem_size) |size| {
6825 .register => |reg| op.* = .{ .reg = reg },6699 const max = @as(u64, math.maxInt(u64)) >>
6826 else => return self.fail("Invalid constraint: '{s}'", .{op_str}),6700 @intCast(u6, 64 - size.bitSize());
6701 if (u > max)
6702 return self.fail("Invalid immediate size: '{s}'", .{op_str});
6827 }6703 }
6828 } else if (mem.startsWith(u8, op_str, "$")) {6704 op.* = .{ .imm = Immediate.u(u) };
6829 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {6705 } else |_| return self.fail("Invalid immediate: '{s}'", .{op_str});
6830 if (mnem_size) |size| {6706 } else return self.fail("Invalid operand: '{s}'", .{op_str});
6831 const max = @as(u64, math.maxInt(u64)) >>6707 } else if (op_it.next()) |op_str| return self.fail("Extra operand: '{s}'", .{op_str});
6832 @intCast(u6, 64 - (size.bitSize() - 1));6708
6833 if ((if (s < 0) ~s else s) > max)6709 (switch (ops[0]) {
6834 return self.fail("Invalid immediate size: '{s}'", .{op_str});6710 .none => self.asmOpOnly(mnem),
6835 }6711 .reg => |reg0| switch (ops[1]) {
6836 op.* = .{ .imm = Immediate.s(s) };6712 .none => self.asmRegister(mnem, reg0),
6837 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {6713 .reg => |reg1| switch (ops[2]) {
6838 if (mnem_size) |size| {6714 .none => self.asmRegisterRegister(mnem, reg1, reg0),
6839 const max = @as(u64, math.maxInt(u64)) >>6715 .reg => |reg2| switch (ops[3]) {
6840 @intCast(u6, 64 - size.bitSize());6716 .none => self.asmRegisterRegisterRegister(mnem, reg2, reg1, reg0),
6841 if (u > max)
6842 return self.fail("Invalid immediate size: '{s}'", .{op_str});
6843 }
6844 op.* = .{ .imm = Immediate.u(u) };
6845 } else |_| return self.fail("Invalid immediate: '{s}'", .{op_str});
6846 } else return self.fail("Invalid operand: '{s}'", .{op_str});
6847 } else if (op_it.next()) |op_str| return self.fail("Extra operand: '{s}'", .{op_str});
6848
6849 (switch (ops[0]) {
6850 .none => self.asmOpOnly(mnem),
6851 .reg => |reg0| switch (ops[1]) {
6852 .none => self.asmRegister(mnem, reg0),
6853 .reg => |reg1| switch (ops[2]) {
6854 .none => self.asmRegisterRegister(mnem, reg1, reg0),
6855 .reg => |reg2| switch (ops[3]) {
6856 .none => self.asmRegisterRegisterRegister(mnem, reg2, reg1, reg0),
6857 else => error.InvalidInstruction,
6858 },
6859 .mem => |mem2| switch (ops[3]) {
6860 .none => self.asmMemoryRegisterRegister(mnem, mem2, reg1, reg0),
6861 else => error.InvalidInstruction,
6862 },
6863 else => error.InvalidInstruction,6717 else => error.InvalidInstruction,
6864 },6718 },
6865 .mem => |mem1| switch (ops[2]) {6719 .mem => |mem2| switch (ops[3]) {
6866 .none => self.asmMemoryRegister(mnem, mem1, reg0),6720 .none => self.asmMemoryRegisterRegister(mnem, mem2, reg1, reg0),
6867 else => error.InvalidInstruction,6721 else => error.InvalidInstruction,
6868 },6722 },
6869 else => error.InvalidInstruction,6723 else => error.InvalidInstruction,
6870 },6724 },
6871 .mem => |mem0| switch (ops[1]) {6725 .mem => |mem1| switch (ops[2]) {
6872 .none => self.asmMemory(mnem, mem0),6726 .none => self.asmMemoryRegister(mnem, mem1, reg0),
6873 .reg => |reg1| switch (ops[2]) {
6874 .none => self.asmRegisterMemory(mnem, reg1, mem0),
6875 else => error.InvalidInstruction,
6876 },
6877 else => error.InvalidInstruction,6727 else => error.InvalidInstruction,
6878 },6728 },
6879 .imm => |imm0| switch (ops[1]) {6729 else => error.InvalidInstruction,
6880 .none => self.asmImmediate(mnem, imm0),6730 },
6881 .reg => |reg1| switch (ops[2]) {6731 .mem => |mem0| switch (ops[1]) {
6882 .none => self.asmRegisterImmediate(mnem, reg1, imm0),6732 .none => self.asmMemory(mnem, mem0),
6883 .reg => |reg2| switch (ops[3]) {6733 .reg => |reg1| switch (ops[2]) {
6884 .none => self.asmRegisterRegisterImmediate(mnem, reg2, reg1, imm0),6734 .none => self.asmRegisterMemory(mnem, reg1, mem0),
6885 else => error.InvalidInstruction,6735 else => error.InvalidInstruction,
6886 },6736 },
6887 .mem => |mem2| switch (ops[3]) {6737 else => error.InvalidInstruction,
6888 .none => self.asmMemoryRegisterImmediate(mnem, mem2, reg1, imm0),6738 },
6889 else => error.InvalidInstruction,6739 .imm => |imm0| switch (ops[1]) {
6890 },6740 .none => self.asmImmediate(mnem, imm0),
6741 .reg => |reg1| switch (ops[2]) {
6742 .none => self.asmRegisterImmediate(mnem, reg1, imm0),
6743 .reg => |reg2| switch (ops[3]) {
6744 .none => self.asmRegisterRegisterImmediate(mnem, reg2, reg1, imm0),
6891 else => error.InvalidInstruction,6745 else => error.InvalidInstruction,
6892 },6746 },
6893 .mem => |mem1| switch (ops[2]) {6747 .mem => |mem2| switch (ops[3]) {
6894 .none => self.asmMemoryImmediate(mnem, mem1, imm0),6748 .none => self.asmMemoryRegisterImmediate(mnem, mem2, reg1, imm0),
6895 else => error.InvalidInstruction,6749 else => error.InvalidInstruction,
6896 },6750 },
6897 else => error.InvalidInstruction,6751 else => error.InvalidInstruction,
6898 },6752 },
6899 }) catch |err| switch (err) {6753 .mem => |mem1| switch (ops[2]) {
6900 error.InvalidInstruction => return self.fail(6754 .none => self.asmMemoryImmediate(mnem, mem1, imm0),
6901 "Invalid instruction: '{s} {s} {s} {s} {s}'",6755 else => error.InvalidInstruction,
6902 .{6756 },
6903 @tagName(mnem),6757 else => error.InvalidInstruction,
6904 @tagName(ops[0]),6758 },
6905 @tagName(ops[1]),6759 }) catch |err| switch (err) {
6906 @tagName(ops[2]),6760 error.InvalidInstruction => return self.fail(
6907 @tagName(ops[3]),6761 "Invalid instruction: '{s} {s} {s} {s} {s}'",
6908 },6762 .{
6909 ),6763 @tagName(mnem),
6910 else => |e| return e,6764 @tagName(ops[0]),
6911 };6765 @tagName(ops[1]),
6912 }6766 @tagName(ops[2]),
6767 @tagName(ops[3]),
6768 },
6769 ),
6770 else => |e| return e,
6771 };
6913 }6772 }
69146773
6915 simple: {6774 simple: {
...@@ -7811,7 +7670,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7811,7 +7670,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
78117670
7812fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {7671fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
7813 const un_op = self.air.instructions.items(.data)[inst].un_op;7672 const un_op = self.air.instructions.items(.data)[inst].un_op;
7814 const result = if (self.liveness.isUnused(inst)) .unreach else result: {7673 const result = result: {
7815 const src_mcv = try self.resolveInst(un_op);7674 const src_mcv = try self.resolveInst(un_op);
7816 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;7675 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
78177676
...@@ -7825,7 +7684,7 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -7825,7 +7684,7 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
78257684
7826fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {7685fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
7827 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7686 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7828 const result = if (self.liveness.isUnused(inst)) .unreach else result: {7687 const result = result: {
7829 const operand = try self.resolveInst(ty_op.operand);7688 const operand = try self.resolveInst(ty_op.operand);
7830 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand;7689 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) break :result operand;
78317690
...@@ -7850,28 +7709,24 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -7850,28 +7709,24 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
7850 const ptr = try self.resolveInst(ty_op.operand);7709 const ptr = try self.resolveInst(ty_op.operand);
7851 const array_ty = ptr_ty.childType();7710 const array_ty = ptr_ty.childType();
7852 const array_len = array_ty.arrayLen();7711 const array_len = array_ty.arrayLen();
7853 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else blk: {7712
7854 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));7713 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
7855 try self.genSetStack(ptr_ty, stack_offset, ptr, .{});7714 try self.genSetStack(ptr_ty, stack_offset, ptr, .{});
7856 try self.genSetStack(Type.u64, stack_offset - 8, .{ .immediate = array_len }, .{});7715 try self.genSetStack(Type.u64, stack_offset - 8, .{ .immediate = array_len }, .{});
7857 break :blk .{ .stack_offset = stack_offset };7716
7858 };7717 const result = MCValue{ .stack_offset = stack_offset };
7859 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });7718 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
7860}7719}
78617720
7862fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {7721fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
7863 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7722 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7864 const result: MCValue = if (self.liveness.isUnused(inst))7723 _ = ty_op;
7865 .unreach7724 return self.fail("TODO implement airIntToFloat for {}", .{self.target.cpu.arch});
7866 else7725 //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
7867 return self.fail("TODO implement airIntToFloat for {}", .{self.target.cpu.arch});
7868 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
7869}7726}
78707727
7871fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {7728fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
7872 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7729 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7873 if (self.liveness.isUnused(inst))
7874 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
78757730
7876 const src_ty = self.air.typeOf(ty_op.operand);7731 const src_ty = self.air.typeOf(ty_op.operand);
7877 const dst_ty = self.air.typeOfIndex(inst);7732 const dst_ty = self.air.typeOfIndex(inst);
...@@ -8255,27 +8110,22 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {...@@ -8255,27 +8110,22 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
8255fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {8110fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
8256 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;8111 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;
82578112
8258 const result: MCValue = result: {8113 const ptr_ty = self.air.typeOf(atomic_load.ptr);
8259 if (self.liveness.isUnused(inst)) break :result .unreach;8114 const ptr_mcv = try self.resolveInst(atomic_load.ptr);
82608115 const ptr_lock = switch (ptr_mcv) {
8261 const ptr_ty = self.air.typeOf(atomic_load.ptr);8116 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8262 const ptr_mcv = try self.resolveInst(atomic_load.ptr);8117 else => null,
8263 const ptr_lock = switch (ptr_mcv) {8118 };
8264 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8119 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
8265 else => null,
8266 };
8267 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
82688120
8269 const dst_mcv =8121 const dst_mcv =
8270 if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv))8122 if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv))
8271 ptr_mcv8123 ptr_mcv
8272 else8124 else
8273 try self.allocRegOrMem(inst, true);8125 try self.allocRegOrMem(inst, true);
82748126
8275 try self.load(dst_mcv, ptr_mcv, ptr_ty);8127 try self.load(dst_mcv, ptr_mcv, ptr_ty);
8276 break :result dst_mcv;8128 return self.finishAir(inst, dst_mcv, .{ atomic_load.ptr, .none, .none });
8277 };
8278 return self.finishAir(inst, result, .{ atomic_load.ptr, .none, .none });
8279}8129}
82808130
8281fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {8131fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {
...@@ -8354,122 +8204,123 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -8354,122 +8204,123 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
8354fn airTagName(self: *Self, inst: Air.Inst.Index) !void {8204fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
8355 const un_op = self.air.instructions.items(.data)[inst].un_op;8205 const un_op = self.air.instructions.items(.data)[inst].un_op;
8356 const operand = try self.resolveInst(un_op);8206 const operand = try self.resolveInst(un_op);
8357 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {8207 _ = operand;
8358 _ = operand;8208 return self.fail("TODO implement airTagName for x86_64", .{});
8359 return self.fail("TODO implement airTagName for x86_64", .{});8209 //return self.finishAir(inst, result, .{ un_op, .none, .none });
8360 };
8361 return self.finishAir(inst, result, .{ un_op, .none, .none });
8362}8210}
83638211
8364fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {8212fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
8365 const un_op = self.air.instructions.items(.data)[inst].un_op;8213 const un_op = self.air.instructions.items(.data)[inst].un_op;
8366 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
8367 const err_ty = self.air.typeOf(un_op);
8368 const err_mcv = try self.resolveInst(un_op);
8369 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);
8370 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);
8371 defer self.register_manager.unlockReg(err_lock);
8372
8373 const addr_reg = try self.register_manager.allocReg(null, gp);
8374 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
8375 defer self.register_manager.unlockReg(addr_lock);
8376
8377 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8378 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(
8379 .{ .kind = .const_data, .ty = Type.anyerror },
8380 4, // dword alignment
8381 );
8382 const got_addr = elf_file.getAtom(atom_index).getOffsetTableAddress(elf_file);
8383 try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{
8384 .base = .ds,
8385 .disp = @intCast(i32, got_addr),
8386 }));
8387 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8388 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(
8389 .{ .kind = .const_data, .ty = Type.anyerror },
8390 4, // dword alignment
8391 );
8392 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
8393 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8394 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8395 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
8396 .{ .kind = .const_data, .ty = Type.anyerror },
8397 4, // dword alignment
8398 );
8399 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
8400 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8401 } else {
8402 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
8403 }
8404
8405 const start_reg = try self.register_manager.allocReg(null, gp);
8406 const start_lock = self.register_manager.lockRegAssumeUnused(start_reg);
8407 defer self.register_manager.unlockReg(start_lock);
84088214
8409 const end_reg = try self.register_manager.allocReg(null, gp);8215 const err_ty = self.air.typeOf(un_op);
8410 const end_lock = self.register_manager.lockRegAssumeUnused(end_reg);8216 const err_mcv = try self.resolveInst(un_op);
8411 defer self.register_manager.unlockReg(end_lock);8217 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);
8218 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);
8219 defer self.register_manager.unlockReg(err_lock);
84128220
8413 try self.truncateRegister(err_ty, err_reg.to32());8221 const addr_reg = try self.register_manager.allocReg(null, gp);
8222 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
8223 defer self.register_manager.unlockReg(addr_lock);
84148224
8415 try self.asmRegisterMemory(.mov, start_reg.to32(), Memory.sib(.dword, .{8225 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8416 .base = addr_reg.to64(),8226 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(
8417 .scale_index = .{ .scale = 4, .index = err_reg.to64() },8227 .{ .kind = .const_data, .ty = Type.anyerror },
8418 .disp = 4,8228 4, // dword alignment
8419 }));8229 );
8420 try self.asmRegisterMemory(.mov, end_reg.to32(), Memory.sib(.dword, .{8230 const got_addr = elf_file.getAtom(atom_index).getOffsetTableAddress(elf_file);
8421 .base = addr_reg.to64(),8231 try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{
8422 .scale_index = .{ .scale = 4, .index = err_reg.to64() },8232 .base = .ds,
8423 .disp = 8,8233 .disp = @intCast(i32, got_addr),
8424 }));
8425 try self.asmRegisterRegister(.sub, end_reg.to32(), start_reg.to32());
8426 try self.asmRegisterMemory(.lea, start_reg.to64(), Memory.sib(.byte, .{
8427 .base = addr_reg.to64(),
8428 .scale_index = .{ .scale = 1, .index = start_reg.to64() },
8429 .disp = 0,
8430 }));
8431 try self.asmRegisterMemory(.lea, end_reg.to32(), Memory.sib(.byte, .{
8432 .base = end_reg.to64(),
8433 .disp = -1,
8434 }));8234 }));
8235 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8236 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(
8237 .{ .kind = .const_data, .ty = Type.anyerror },
8238 4, // dword alignment
8239 );
8240 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
8241 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8242 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8243 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(
8244 .{ .kind = .const_data, .ty = Type.anyerror },
8245 4, // dword alignment
8246 );
8247 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
8248 try self.genSetReg(Type.usize, addr_reg, .{ .load_got = sym_index });
8249 } else {
8250 return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
8251 }
84358252
8436 const dst_mcv = try self.allocRegOrMem(inst, false);8253 const start_reg = try self.register_manager.allocReg(null, gp);
8437 try self.asmMemoryRegister(.mov, Memory.sib(.qword, .{8254 const start_lock = self.register_manager.lockRegAssumeUnused(start_reg);
8438 .base = .rbp,8255 defer self.register_manager.unlockReg(start_lock);
8439 .disp = 0 - dst_mcv.stack_offset,8256
8440 }), start_reg.to64());8257 const end_reg = try self.register_manager.allocReg(null, gp);
8441 try self.asmMemoryRegister(.mov, Memory.sib(.qword, .{8258 const end_lock = self.register_manager.lockRegAssumeUnused(end_reg);
8442 .base = .rbp,8259 defer self.register_manager.unlockReg(end_lock);
8443 .disp = 8 - dst_mcv.stack_offset,8260
8444 }), end_reg.to64());8261 try self.truncateRegister(err_ty, err_reg.to32());
8445 break :result dst_mcv;8262
8446 };8263 try self.asmRegisterMemory(.mov, start_reg.to32(), Memory.sib(.dword, .{
8447 return self.finishAir(inst, result, .{ un_op, .none, .none });8264 .base = addr_reg.to64(),
8265 .scale_index = .{ .scale = 4, .index = err_reg.to64() },
8266 .disp = 4,
8267 }));
8268 try self.asmRegisterMemory(.mov, end_reg.to32(), Memory.sib(.dword, .{
8269 .base = addr_reg.to64(),
8270 .scale_index = .{ .scale = 4, .index = err_reg.to64() },
8271 .disp = 8,
8272 }));
8273 try self.asmRegisterRegister(.sub, end_reg.to32(), start_reg.to32());
8274 try self.asmRegisterMemory(.lea, start_reg.to64(), Memory.sib(.byte, .{
8275 .base = addr_reg.to64(),
8276 .scale_index = .{ .scale = 1, .index = start_reg.to64() },
8277 .disp = 0,
8278 }));
8279 try self.asmRegisterMemory(.lea, end_reg.to32(), Memory.sib(.byte, .{
8280 .base = end_reg.to64(),
8281 .disp = -1,
8282 }));
8283
8284 const dst_mcv = try self.allocRegOrMem(inst, false);
8285 try self.asmMemoryRegister(.mov, Memory.sib(.qword, .{
8286 .base = .rbp,
8287 .disp = 0 - dst_mcv.stack_offset,
8288 }), start_reg.to64());
8289 try self.asmMemoryRegister(.mov, Memory.sib(.qword, .{
8290 .base = .rbp,
8291 .disp = 8 - dst_mcv.stack_offset,
8292 }), end_reg.to64());
8293
8294 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
8448}8295}
84498296
8450fn airSplat(self: *Self, inst: Air.Inst.Index) !void {8297fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
8451 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8298 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8452 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSplat for x86_64", .{});8299 _ = ty_op;
8453 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });8300 return self.fail("TODO implement airSplat for x86_64", .{});
8301 //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
8454}8302}
84558303
8456fn airSelect(self: *Self, inst: Air.Inst.Index) !void {8304fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
8457 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8305 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8458 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;8306 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
8459 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSelect for x86_64", .{});8307 _ = extra;
8460 return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });8308 return self.fail("TODO implement airSelect for x86_64", .{});
8309 //return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });
8461}8310}
84628311
8463fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {8312fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
8464 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8313 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8465 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airShuffle for x86_64", .{});8314 _ = ty_op;
8466 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });8315 return self.fail("TODO implement airShuffle for x86_64", .{});
8316 //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
8467}8317}
84688318
8469fn airReduce(self: *Self, inst: Air.Inst.Index) !void {8319fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
8470 const reduce = self.air.instructions.items(.data)[inst].reduce;8320 const reduce = self.air.instructions.items(.data)[inst].reduce;
8471 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airReduce for x86_64", .{});8321 _ = reduce;
8472 return self.finishAir(inst, result, .{ reduce.operand, .none, .none });8322 return self.fail("TODO implement airReduce for x86_64", .{});
8323 //return self.finishAir(inst, result, .{ reduce.operand, .none, .none });
8473}8324}
84748325
8475fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {8326fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
...@@ -8479,8 +8330,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8479,8 +8330,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8479 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);8330 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
8480 const abi_size = @intCast(u32, result_ty.abiSize(self.target.*));8331 const abi_size = @intCast(u32, result_ty.abiSize(self.target.*));
8481 const abi_align = result_ty.abiAlignment(self.target.*);8332 const abi_align = result_ty.abiAlignment(self.target.*);
8482 const result: MCValue = res: {8333 const result: MCValue = result: {
8483 if (self.liveness.isUnused(inst)) break :res MCValue.unreach;
8484 switch (result_ty.zigTypeTag()) {8334 switch (result_ty.zigTypeTag()) {
8485 .Struct => {8335 .Struct => {
8486 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));8336 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
...@@ -8571,7 +8421,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8571,7 +8421,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8571 };8421 };
8572 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});8422 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});
8573 }8423 }
8574 break :res .{ .stack_offset = stack_offset };8424 break :result .{ .stack_offset = stack_offset };
8575 },8425 },
8576 .Array => {8426 .Array => {
8577 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));8427 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
...@@ -8587,7 +8437,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8587,7 +8437,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8587 const elem_off = @intCast(i32, elem_size * elem_i);8437 const elem_off = @intCast(i32, elem_size * elem_i);
8588 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});8438 try self.genSetStack(elem_ty, stack_offset - elem_off, mat_elem_mcv, .{});
8589 }8439 }
8590 break :res MCValue{ .stack_offset = stack_offset };8440 break :result MCValue{ .stack_offset = stack_offset };
8591 },8441 },
8592 .Vector => return self.fail("TODO implement aggregate_init for vectors", .{}),8442 .Vector => return self.fail("TODO implement aggregate_init for vectors", .{}),
8593 else => unreachable,8443 else => unreachable,
...@@ -8607,11 +8457,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -8607,11 +8457,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
8607fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {8457fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
8608 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8458 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
8609 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;8459 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
8610 const result: MCValue = res: {8460 _ = extra;
8611 if (self.liveness.isUnused(inst)) break :res MCValue.unreach;8461 return self.fail("TODO implement airAggregateInit for x86_64", .{});
8612 return self.fail("TODO implement airAggregateInit for x86_64", .{});8462 //return self.finishAir(inst, result, .{ extra.init, .none, .none });
8613 };
8614 return self.finishAir(inst, result, .{ extra.init, .none, .none });
8615}8463}
86168464
8617fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {8465fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
...@@ -8622,10 +8470,9 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {...@@ -8622,10 +8470,9 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
8622fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {8470fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
8623 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8471 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8624 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;8472 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
8625 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {8473 _ = extra;
8626 return self.fail("TODO implement airMulAdd for x86_64", .{});8474 return self.fail("TODO implement airMulAdd for x86_64", .{});
8627 };8475 //return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
8628 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
8629}8476}
86308477
8631fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {8478fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {