| ... | @@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1738 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); | 1738 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1739 | } | 1739 | } |
| 1740 | const err_union_ty = self.air.typeOf(ty_op.operand); | 1740 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| | 1741 | const err_ty = err_union_ty.errorUnionSet(); |
| 1741 | const payload_ty = err_union_ty.errorUnionPayload(); | 1742 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1742 | const operand = try self.resolveInst(ty_op.operand); | 1743 | const operand = try self.resolveInst(ty_op.operand); |
| | 1744 | operand.freezeIfRegister(&self.register_manager); |
| | 1745 | defer operand.unfreezeIfRegister(&self.register_manager); |
| | 1746 | |
| 1743 | const result: MCValue = result: { | 1747 | const result: MCValue = result: { |
| 1744 | if (!payload_ty.hasRuntimeBits()) break :result operand; | 1748 | if (!payload_ty.hasRuntimeBits()) break :result operand; |
| 1745 | switch (operand) { | 1749 | switch (operand) { |
| 1746 | .stack_offset => |off| { | 1750 | .stack_offset => |off| { |
| 1747 | break :result MCValue{ .stack_offset = off }; | 1751 | break :result MCValue{ .stack_offset = off }; |
| 1748 | }, | 1752 | }, |
| | 1753 | .register => { |
| | 1754 | // TODO reuse operand |
| | 1755 | break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand); |
| | 1756 | }, |
| 1749 | else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}), | 1757 | else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}), |
| 1750 | } | 1758 | } |
| 1751 | }; | 1759 | }; |
| ... | @@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1763 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; | 1771 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; |
| 1764 | | 1772 | |
| 1765 | const operand = try self.resolveInst(ty_op.operand); | 1773 | const operand = try self.resolveInst(ty_op.operand); |
| | 1774 | operand.freezeIfRegister(&self.register_manager); |
| | 1775 | defer operand.unfreezeIfRegister(&self.register_manager); |
| | 1776 | |
| 1766 | const err_ty = err_union_ty.errorUnionSet(); | 1777 | const err_ty = err_union_ty.errorUnionSet(); |
| 1767 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); | | |
| 1768 | switch (operand) { | 1778 | switch (operand) { |
| 1769 | .stack_offset => |off| { | 1779 | .stack_offset => |off| { |
| | 1780 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); |
| 1770 | const offset = off - @intCast(i32, err_abi_size); | 1781 | const offset = off - @intCast(i32, err_abi_size); |
| 1771 | break :result MCValue{ .stack_offset = offset }; | 1782 | break :result MCValue{ .stack_offset = offset }; |
| 1772 | }, | 1783 | }, |
| | 1784 | .register => { |
| | 1785 | // TODO reuse operand |
| | 1786 | const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); |
| | 1787 | try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*))); |
| | 1788 | break :result MCValue{ |
| | 1789 | .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))), |
| | 1790 | }; |
| | 1791 | }, |
| 1773 | else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}), | 1792 | else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}), |
| 1774 | } | 1793 | } |
| 1775 | }; | 1794 | }; |
| ... | @@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2686 | }; | 2705 | }; |
| 2687 | | 2706 | |
| 2688 | // Shift by struct_field_offset. | 2707 | // Shift by struct_field_offset. |
| 2689 | const shift_amount = @intCast(u8, struct_field_offset * 8); | 2708 | const shift = @intCast(u8, struct_field_offset * 8); |
| 2690 | if (shift_amount > 0) { | 2709 | try self.shiftRegister(dst_mcv.register, shift); |
| 2691 | if (shift_amount == 1) { | | |
| 2692 | _ = try self.addInst(.{ | | |
| 2693 | .tag = .shr, | | |
| 2694 | .ops = (Mir.Ops{ | | |
| 2695 | .reg1 = dst_mcv.register, | | |
| 2696 | }).encode(), | | |
| 2697 | .data = undefined, | | |
| 2698 | }); | | |
| 2699 | } else { | | |
| 2700 | _ = try self.addInst(.{ | | |
| 2701 | .tag = .shr, | | |
| 2702 | .ops = (Mir.Ops{ | | |
| 2703 | .reg1 = dst_mcv.register, | | |
| 2704 | .flags = 0b10, | | |
| 2705 | }).encode(), | | |
| 2706 | .data = .{ .imm = shift_amount }, | | |
| 2707 | }); | | |
| 2708 | } | | |
| 2709 | } | | |
| 2710 | | 2710 | |
| 2711 | // Mask with reg.size() - struct_field_size | 2711 | // Mask with reg.size() - struct_field_size |
| 2712 | const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*))); | 2712 | const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*))); |
| ... | @@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { | ... | @@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 5768 | unreachable; // TODO handle floating-point registers | 5768 | unreachable; // TODO handle floating-point registers |
| 5769 | } | 5769 | } |
| 5770 | } | 5770 | } |
| | 5771 | |
| | 5772 | fn shiftRegister(self: *Self, reg: Register, shift: u8) !void { |
| | 5773 | if (shift == 0) return; |
| | 5774 | if (shift == 1) { |
| | 5775 | _ = try self.addInst(.{ |
| | 5776 | .tag = .shr, |
| | 5777 | .ops = (Mir.Ops{ |
| | 5778 | .reg1 = reg, |
| | 5779 | }).encode(), |
| | 5780 | .data = undefined, |
| | 5781 | }); |
| | 5782 | } else { |
| | 5783 | _ = try self.addInst(.{ |
| | 5784 | .tag = .shr, |
| | 5785 | .ops = (Mir.Ops{ |
| | 5786 | .reg1 = reg, |
| | 5787 | .flags = 0b10, |
| | 5788 | }).encode(), |
| | 5789 | .data = .{ .imm = shift }, |
| | 5790 | }); |
| | 5791 | } |
| | 5792 | } |