| ... | ... | @@ -1628,23 +1628,44 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1628 | 1628 | |
| 1629 | 1629 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1630 | 1630 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1631 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1632 | | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1633 | | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1634 | | const mcv = try self.resolveInst(ty_op.operand); |
| 1635 | | if (!payload_ty.hasRuntimeBits()) break :result mcv; |
| 1636 | | return self.fail("TODO implement unwrap error union error for non-empty payloads", .{}); |
| 1631 | if (self.liveness.isUnused(inst)) { |
| 1632 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1633 | } |
| 1634 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1635 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1636 | const operand = try self.resolveInst(ty_op.operand); |
| 1637 | const result: MCValue = result: { |
| 1638 | if (!payload_ty.hasRuntimeBits()) break :result operand; |
| 1639 | switch (operand) { |
| 1640 | .stack_offset => |off| { |
| 1641 | break :result MCValue{ .stack_offset = off }; |
| 1642 | }, |
| 1643 | else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}), |
| 1644 | } |
| 1637 | 1645 | }; |
| 1638 | 1646 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1639 | 1647 | } |
| 1640 | 1648 | |
| 1641 | 1649 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1642 | 1650 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1643 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1644 | | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1645 | | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1651 | if (self.liveness.isUnused(inst)) { |
| 1652 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1653 | } |
| 1654 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1655 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1656 | const result: MCValue = result: { |
| 1646 | 1657 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; |
| 1647 | | return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{}); |
| 1658 | |
| 1659 | const operand = try self.resolveInst(ty_op.operand); |
| 1660 | const err_ty = err_union_ty.errorUnionSet(); |
| 1661 | const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); |
| 1662 | switch (operand) { |
| 1663 | .stack_offset => |off| { |
| 1664 | const offset = off - @intCast(i32, err_abi_size); |
| 1665 | break :result MCValue{ .stack_offset = offset }; |
| 1666 | }, |
| 1667 | else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}), |
| 1668 | } |
| 1648 | 1669 | }; |
| 1649 | 1670 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1650 | 1671 | } |
| ... | ... | @@ -3166,8 +3187,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 3166 | 3187 | switch (self.ret_mcv) { |
| 3167 | 3188 | .stack_offset => { |
| 3168 | 3189 | // TODO audit register allocation! |
| 3169 | | self.register_manager.freezeRegs(&.{.rdi}); |
| 3170 | | defer self.register_manager.unfreezeRegs(&.{.rdi}); |
| 3190 | self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi }); |
| 3191 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi }); |
| 3171 | 3192 | const reg = try self.register_manager.allocReg(null); |
| 3172 | 3193 | self.ret_backpatch = try self.addInst(.{ |
| 3173 | 3194 | .tag = .mov, |
| ... | ... | @@ -3509,8 +3530,8 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3509 | 3530 | return self.fail("TODO isErr for errors with size larger than register size", .{}); |
| 3510 | 3531 | } |
| 3511 | 3532 | } else { |
| 3512 | | log.warn("operand = {}, payload_type = {}", .{ operand, payload_type }); |
| 3513 | | return self.fail("TODO isErr for non-empty payloads", .{}); |
| 3533 | try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 }); |
| 3534 | return MCValue{ .compare_flags_unsigned = .gt }; |
| 3514 | 3535 | } |
| 3515 | 3536 | } |
| 3516 | 3537 | |
| ... | ... | @@ -4229,6 +4250,8 @@ const InlineMemcpyOpts = struct { |
| 4229 | 4250 | fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 4230 | 4251 | const abi_size = ty.abiSize(self.target.*); |
| 4231 | 4252 | |
| 4253 | // TODO this is wrong. We should check first if any of the operands is in `.rax` or `.rcx` before |
| 4254 | // spilling. Consolidate with other TODOs regarding register allocation mechanics. |
| 4232 | 4255 | try self.register_manager.getReg(.rax, null); |
| 4233 | 4256 | try self.register_manager.getReg(.rcx, null); |
| 4234 | 4257 | |