| ... | ... | @@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1738 | 1738 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1739 | 1739 | } |
| 1740 | 1740 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1741 | const err_ty = err_union_ty.errorUnionSet(); |
| 1741 | 1742 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1742 | 1743 | const operand = try self.resolveInst(ty_op.operand); |
| 1744 | operand.freezeIfRegister(&self.register_manager); |
| 1745 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 1746 | |
| 1743 | 1747 | const result: MCValue = result: { |
| 1744 | 1748 | if (!payload_ty.hasRuntimeBits()) break :result operand; |
| 1745 | 1749 | switch (operand) { |
| 1746 | 1750 | .stack_offset => |off| { |
| 1747 | 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 | 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 | 1771 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; |
| 1764 | 1772 | |
| 1765 | 1773 | const operand = try self.resolveInst(ty_op.operand); |
| 1774 | operand.freezeIfRegister(&self.register_manager); |
| 1775 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 1776 | |
| 1766 | 1777 | const err_ty = err_union_ty.errorUnionSet(); |
| 1767 | | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); |
| 1768 | 1778 | switch (operand) { |
| 1769 | 1779 | .stack_offset => |off| { |
| 1780 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); |
| 1770 | 1781 | const offset = off - @intCast(i32, err_abi_size); |
| 1771 | 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 | 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 | 2705 | }; |
| 2687 | 2706 | |
| 2688 | 2707 | // Shift by struct_field_offset. |
| 2689 | | const shift_amount = @intCast(u8, struct_field_offset * 8); |
| 2690 | | if (shift_amount > 0) { |
| 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 | | } |
| 2708 | const shift = @intCast(u8, struct_field_offset * 8); |
| 2709 | try self.shiftRegister(dst_mcv.register, shift); |
| 2710 | 2710 | |
| 2711 | 2711 | // Mask with reg.size() - struct_field_size |
| 2712 | 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 | 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 | } |