| ... | @@ -3776,9 +3776,13 @@ fn zirCmp( | ... | @@ -3776,9 +3776,13 @@ fn zirCmp( |
| 3776 | const tracy = trace(@src()); | 3776 | const tracy = trace(@src()); |
| 3777 | defer tracy.end(); | 3777 | defer tracy.end(); |
| 3778 | | 3778 | |
| | 3779 | const mod = sema.mod; |
| | 3780 | |
| 3779 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 3781 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 3780 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; | 3782 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; |
| 3781 | const src: LazySrcLoc = inst_data.src(); | 3783 | const src: LazySrcLoc = inst_data.src(); |
| | 3784 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| | 3785 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 3782 | const lhs = try sema.resolveInst(extra.lhs); | 3786 | const lhs = try sema.resolveInst(extra.lhs); |
| 3783 | const rhs = try sema.resolveInst(extra.rhs); | 3787 | const rhs = try sema.resolveInst(extra.rhs); |
| 3784 | | 3788 | |
| ... | @@ -3790,7 +3794,7 @@ fn zirCmp( | ... | @@ -3790,7 +3794,7 @@ fn zirCmp( |
| 3790 | const rhs_ty_tag = rhs.ty.zigTypeTag(); | 3794 | const rhs_ty_tag = rhs.ty.zigTypeTag(); |
| 3791 | if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) { | 3795 | if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) { |
| 3792 | // null == null, null != null | 3796 | // null == null, null != null |
| 3793 | return sema.mod.constBool(sema.arena, src, op == .eq); | 3797 | return mod.constBool(sema.arena, src, op == .eq); |
| 3794 | } else if (is_equality_cmp and | 3798 | } else if (is_equality_cmp and |
| 3795 | ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or | 3799 | ((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or |
| 3796 | rhs_ty_tag == .Null and lhs_ty_tag == .Optional)) | 3800 | rhs_ty_tag == .Null and lhs_ty_tag == .Optional)) |
| ... | @@ -3801,23 +3805,23 @@ fn zirCmp( | ... | @@ -3801,23 +3805,23 @@ fn zirCmp( |
| 3801 | } else if (is_equality_cmp and | 3805 | } else if (is_equality_cmp and |
| 3802 | ((lhs_ty_tag == .Null and rhs.ty.isCPtr()) or (rhs_ty_tag == .Null and lhs.ty.isCPtr()))) | 3806 | ((lhs_ty_tag == .Null and rhs.ty.isCPtr()) or (rhs_ty_tag == .Null and lhs.ty.isCPtr()))) |
| 3803 | { | 3807 | { |
| 3804 | return sema.mod.fail(&block.base, src, "TODO implement C pointer cmp", .{}); | 3808 | return mod.fail(&block.base, src, "TODO implement C pointer cmp", .{}); |
| 3805 | } else if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { | 3809 | } else if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { |
| 3806 | const non_null_type = if (lhs_ty_tag == .Null) rhs.ty else lhs.ty; | 3810 | const non_null_type = if (lhs_ty_tag == .Null) rhs.ty else lhs.ty; |
| 3807 | return sema.mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type}); | 3811 | return mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type}); |
| 3808 | } else if (is_equality_cmp and | 3812 | } else if (is_equality_cmp and |
| 3809 | ((lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) or | 3813 | ((lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) or |
| 3810 | (rhs_ty_tag == .EnumLiteral and lhs_ty_tag == .Union))) | 3814 | (rhs_ty_tag == .EnumLiteral and lhs_ty_tag == .Union))) |
| 3811 | { | 3815 | { |
| 3812 | return sema.mod.fail(&block.base, src, "TODO implement equality comparison between a union's tag value and an enum literal", .{}); | 3816 | return mod.fail(&block.base, src, "TODO implement equality comparison between a union's tag value and an enum literal", .{}); |
| 3813 | } else if (lhs_ty_tag == .ErrorSet and rhs_ty_tag == .ErrorSet) { | 3817 | } else if (lhs_ty_tag == .ErrorSet and rhs_ty_tag == .ErrorSet) { |
| 3814 | if (!is_equality_cmp) { | 3818 | if (!is_equality_cmp) { |
| 3815 | return sema.mod.fail(&block.base, src, "{s} operator not allowed for errors", .{@tagName(op)}); | 3819 | return mod.fail(&block.base, src, "{s} operator not allowed for errors", .{@tagName(op)}); |
| 3816 | } | 3820 | } |
| 3817 | if (rhs.value()) |rval| { | 3821 | if (rhs.value()) |rval| { |
| 3818 | if (lhs.value()) |lval| { | 3822 | if (lhs.value()) |lval| { |
| 3819 | // TODO optimisation oppurtunity: evaluate if std.mem.eql is faster with the names, or calling to Module.getErrorValue to get the values and then compare them is faster | 3823 | // TODO optimisation oppurtunity: evaluate if std.mem.eql is faster with the names, or calling to Module.getErrorValue to get the values and then compare them is faster |
| 3820 | return sema.mod.constBool(sema.arena, src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq)); | 3824 | return mod.constBool(sema.arena, src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq)); |
| 3821 | } | 3825 | } |
| 3822 | } | 3826 | } |
| 3823 | try sema.requireRuntimeBlock(block, src); | 3827 | try sema.requireRuntimeBlock(block, src); |
| ... | @@ -3829,11 +3833,30 @@ fn zirCmp( | ... | @@ -3829,11 +3833,30 @@ fn zirCmp( |
| 3829 | return sema.cmpNumeric(block, src, lhs, rhs, op); | 3833 | return sema.cmpNumeric(block, src, lhs, rhs, op); |
| 3830 | } else if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) { | 3834 | } else if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) { |
| 3831 | if (!is_equality_cmp) { | 3835 | if (!is_equality_cmp) { |
| 3832 | return sema.mod.fail(&block.base, src, "{s} operator not allowed for types", .{@tagName(op)}); | 3836 | return mod.fail(&block.base, src, "{s} operator not allowed for types", .{@tagName(op)}); |
| 3833 | } | 3837 | } |
| 3834 | return sema.mod.constBool(sema.arena, src, lhs.value().?.eql(rhs.value().?) == (op == .eq)); | 3838 | return mod.constBool(sema.arena, src, lhs.value().?.eql(rhs.value().?) == (op == .eq)); |
| | 3839 | } |
| | 3840 | |
| | 3841 | const instructions = &[_]*Inst{ lhs, rhs }; |
| | 3842 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions); |
| | 3843 | if (!resolved_type.isSelfComparable(is_equality_cmp)) { |
| | 3844 | return mod.fail(&block.base, src, "operator not allowed for type '{}'", .{resolved_type}); |
| 3835 | } | 3845 | } |
| 3836 | return sema.mod.fail(&block.base, src, "TODO implement more cmp analysis", .{}); | 3846 | |
| | 3847 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| | 3848 | const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src); |
| | 3849 | try sema.requireRuntimeBlock(block, src); // TODO try to do it at comptime |
| | 3850 | const bool_type = Type.initTag(.bool); // TODO handle vectors |
| | 3851 | const tag: Inst.Tag = switch (op) { |
| | 3852 | .lt => .cmp_lt, |
| | 3853 | .lte => .cmp_lte, |
| | 3854 | .eq => .cmp_eq, |
| | 3855 | .gte => .cmp_gte, |
| | 3856 | .gt => .cmp_gt, |
| | 3857 | .neq => .cmp_neq, |
| | 3858 | }; |
| | 3859 | return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs); |
| 3837 | } | 3860 | } |
| 3838 | | 3861 | |
| 3839 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 3862 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |