| ... | ... | @@ -4562,18 +4562,21 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4562 | 4562 | return self.finishAir(inst, .unreach, .{ .none, .none, .none }); |
| 4563 | 4563 | } |
| 4564 | 4564 | |
| 4565 | | fn isNull(self: *Self, operand: MCValue) !MCValue { |
| 4566 | | _ = operand; |
| 4567 | | // Here you can specialize this instruction if it makes sense to, otherwise the default |
| 4568 | | // will call isNonNull and invert the result. |
| 4569 | | return self.fail("TODO call isNonNull and invert the result", .{}); |
| 4565 | fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { |
| 4566 | if (operand_ty.isPtrLikeOptional()) { |
| 4567 | assert(operand_ty.abiSize(self.target.*) == 8); |
| 4568 | |
| 4569 | const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } }; |
| 4570 | return self.cmp(operand_bind, imm_bind, Type.usize, .eq); |
| 4571 | } else { |
| 4572 | return self.fail("TODO implement non-pointer optionals", .{}); |
| 4573 | } |
| 4570 | 4574 | } |
| 4571 | 4575 | |
| 4572 | | fn isNonNull(self: *Self, operand: MCValue) !MCValue { |
| 4573 | | _ = operand; |
| 4574 | | // Here you can specialize this instruction if it makes sense to, otherwise the default |
| 4575 | | // will call isNull and invert the result. |
| 4576 | | return self.fail("TODO call isNull and invert the result", .{}); |
| 4576 | fn isNonNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { |
| 4577 | const is_null_res = try self.isNull(operand_bind, operand_ty); |
| 4578 | assert(is_null_res.compare_flags == .eq); |
| 4579 | return MCValue{ .compare_flags = is_null_res.compare_flags.negate() }; |
| 4577 | 4580 | } |
| 4578 | 4581 | |
| 4579 | 4582 | fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| ... | ... | @@ -4605,8 +4608,10 @@ fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 4605 | 4608 | fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { |
| 4606 | 4609 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4607 | 4610 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4608 | | const operand = try self.resolveInst(un_op); |
| 4609 | | break :result try self.isNull(operand); |
| 4611 | const operand_bind: ReadArg.Bind = .{ .inst = un_op }; |
| 4612 | const operand_ty = self.air.typeOf(un_op); |
| 4613 | |
| 4614 | break :result try self.isNull(operand_bind, operand_ty); |
| 4610 | 4615 | }; |
| 4611 | 4616 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4612 | 4617 | } |
| ... | ... | @@ -4621,7 +4626,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4621 | 4626 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4622 | 4627 | try self.load(operand, operand_ptr, ptr_ty); |
| 4623 | 4628 | |
| 4624 | | break :result try self.isNull(operand); |
| 4629 | break :result try self.isNull(.{ .mcv = operand }, elem_ty); |
| 4625 | 4630 | }; |
| 4626 | 4631 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4627 | 4632 | } |
| ... | ... | @@ -4629,8 +4634,10 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4629 | 4634 | fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| 4630 | 4635 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4631 | 4636 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4632 | | const operand = try self.resolveInst(un_op); |
| 4633 | | break :result try self.isNonNull(operand); |
| 4637 | const operand_bind: ReadArg.Bind = .{ .inst = un_op }; |
| 4638 | const operand_ty = self.air.typeOf(un_op); |
| 4639 | |
| 4640 | break :result try self.isNonNull(operand_bind, operand_ty); |
| 4634 | 4641 | }; |
| 4635 | 4642 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4636 | 4643 | } |
| ... | ... | @@ -4645,7 +4652,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4645 | 4652 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4646 | 4653 | try self.load(operand, operand_ptr, ptr_ty); |
| 4647 | 4654 | |
| 4648 | | break :result try self.isNonNull(operand); |
| 4655 | break :result try self.isNonNull(.{ .mcv = operand }, elem_ty); |
| 4649 | 4656 | }; |
| 4650 | 4657 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4651 | 4658 | } |