| ... | @@ -1628,23 +1628,44 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1628,23 +1628,44 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1628 | | 1628 | |
| 1629 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { | 1629 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1630 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1630 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1631 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1631 | if (self.liveness.isUnused(inst)) { |
| 1632 | const err_union_ty = self.air.typeOf(ty_op.operand); | 1632 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1633 | const payload_ty = err_union_ty.errorUnionPayload(); | 1633 | } |
| 1634 | const mcv = try self.resolveInst(ty_op.operand); | 1634 | const err_union_ty = self.air.typeOf(ty_op.operand); |
| 1635 | if (!payload_ty.hasRuntimeBits()) break :result mcv; | 1635 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 1636 | return self.fail("TODO implement unwrap error union error for non-empty payloads", .{}); | 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 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1646 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1639 | } | 1647 | } |
| 1640 | | 1648 | |
| 1641 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | 1649 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1642 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1650 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1643 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1651 | if (self.liveness.isUnused(inst)) { |
| 1644 | const err_union_ty = self.air.typeOf(ty_op.operand); | 1652 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1645 | const payload_ty = err_union_ty.errorUnionPayload(); | 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 | if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; | 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 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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,8 +3187,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 3166 | switch (self.ret_mcv) { | 3187 | switch (self.ret_mcv) { |
| 3167 | .stack_offset => { | 3188 | .stack_offset => { |
| 3168 | // TODO audit register allocation! | 3189 | // TODO audit register allocation! |
| 3169 | self.register_manager.freezeRegs(&.{.rdi}); | 3190 | self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi }); |
| 3170 | defer self.register_manager.unfreezeRegs(&.{.rdi}); | 3191 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi }); |
| 3171 | const reg = try self.register_manager.allocReg(null); | 3192 | const reg = try self.register_manager.allocReg(null); |
| 3172 | self.ret_backpatch = try self.addInst(.{ | 3193 | self.ret_backpatch = try self.addInst(.{ |
| 3173 | .tag = .mov, | 3194 | .tag = .mov, |
| ... | @@ -3509,8 +3530,8 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -3509,8 +3530,8 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3509 | return self.fail("TODO isErr for errors with size larger than register size", .{}); | 3530 | return self.fail("TODO isErr for errors with size larger than register size", .{}); |
| 3510 | } | 3531 | } |
| 3511 | } else { | 3532 | } else { |
| 3512 | log.warn("operand = {}, payload_type = {}", .{ operand, payload_type }); | 3533 | try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 }); |
| 3513 | return self.fail("TODO isErr for non-empty payloads", .{}); | 3534 | return MCValue{ .compare_flags_unsigned = .gt }; |
| 3514 | } | 3535 | } |
| 3515 | } | 3536 | } |
| 3516 | | 3537 | |
| ... | @@ -4229,6 +4250,8 @@ const InlineMemcpyOpts = struct { | ... | @@ -4229,6 +4250,8 @@ const InlineMemcpyOpts = struct { |
| 4229 | fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: InlineMemcpyOpts) InnerError!void { | 4250 | fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 4230 | const abi_size = ty.abiSize(self.target.*); | 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 | try self.register_manager.getReg(.rax, null); | 4255 | try self.register_manager.getReg(.rax, null); |
| 4233 | try self.register_manager.getReg(.rcx, null); | 4256 | try self.register_manager.getReg(.rcx, null); |
| 4234 | | 4257 | |