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