| ... | ... | @@ -2228,7 +2228,6 @@ fn zirEnumDecl( |
| 2228 | 2228 | enum_obj.tag_ty_inferred = true; |
| 2229 | 2229 | } |
| 2230 | 2230 | } |
| 2231 | | const target = mod.getTarget(); |
| 2232 | 2231 | |
| 2233 | 2232 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 2234 | 2233 | const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { |
| ... | ... | @@ -2291,7 +2290,7 @@ fn zirEnumDecl( |
| 2291 | 2290 | }); |
| 2292 | 2291 | } else if (any_values) { |
| 2293 | 2292 | const tag_val = if (last_tag_val) |val| |
| 2294 | | try val.intAdd(Value.one, enum_obj.tag_ty, sema.arena, target) |
| 2293 | try sema.intAdd(block, src, val, Value.one, enum_obj.tag_ty) |
| 2295 | 2294 | else |
| 2296 | 2295 | Value.zero; |
| 2297 | 2296 | last_tag_val = tag_val; |
| ... | ... | @@ -6054,7 +6053,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 6054 | 6053 | if (int_val.isUndef()) { |
| 6055 | 6054 | return sema.failWithUseOfUndef(block, operand_src); |
| 6056 | 6055 | } |
| 6057 | | if (!dest_ty.enumHasInt(int_val, sema.mod)) { |
| 6056 | if (!(try sema.enumHasInt(block, src, dest_ty, int_val))) { |
| 6058 | 6057 | const msg = msg: { |
| 6059 | 6058 | const msg = try sema.errMsg( |
| 6060 | 6059 | block, |
| ... | ... | @@ -7082,7 +7081,7 @@ fn intCast( |
| 7082 | 7081 | // range to account for negative values. |
| 7083 | 7082 | const dest_range_val = if (wanted_info.signedness == .signed) range_val: { |
| 7084 | 7083 | const range_minus_one = try dest_max_val.shl(Value.one, unsigned_operand_ty, sema.arena, target); |
| 7085 | | break :range_val try range_minus_one.intAdd(Value.one, unsigned_operand_ty, sema.arena, target); |
| 7084 | break :range_val try sema.intAdd(block, operand_src, range_minus_one, Value.one, unsigned_operand_ty); |
| 7086 | 7085 | } else dest_max_val; |
| 7087 | 7086 | const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val); |
| 7088 | 7087 | |
| ... | ... | @@ -7236,8 +7235,8 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 7236 | 7235 | ), |
| 7237 | 7236 | } |
| 7238 | 7237 | |
| 7239 | | if (try sema.isComptimeKnown(block, operand_src, operand)) { |
| 7240 | | return sema.coerce(block, dest_ty, operand, operand_src); |
| 7238 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { |
| 7239 | return sema.addConstant(dest_ty, try operand_val.floatCast(sema.arena, dest_ty, target)); |
| 7241 | 7240 | } |
| 7242 | 7241 | if (dest_is_comptime_float) { |
| 7243 | 7242 | return sema.fail(block, src, "unable to cast runtime value to 'comptime_float'", .{}); |
| ... | ... | @@ -8203,8 +8202,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8203 | 8202 | // Validation above ensured these will succeed. |
| 8204 | 8203 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable; |
| 8205 | 8204 | const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable; |
| 8206 | | if (Value.compare(operand_val, .gte, first_tv.val, operand_ty, sema.mod) and |
| 8207 | | Value.compare(operand_val, .lte, last_tv.val, operand_ty, sema.mod)) |
| 8205 | if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and |
| 8206 | (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty))) |
| 8208 | 8207 | { |
| 8209 | 8208 | return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); |
| 8210 | 8209 | } |
| ... | ... | @@ -8878,7 +8877,7 @@ fn zirShl( |
| 8878 | 8877 | if (rhs_val.isUndef()) { |
| 8879 | 8878 | return sema.addConstUndef(sema.typeOf(lhs)); |
| 8880 | 8879 | } |
| 8881 | | if (rhs_val.compareWithZero(.eq)) { |
| 8880 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 8882 | 8881 | return lhs; |
| 8883 | 8882 | } |
| 8884 | 8883 | } |
| ... | ... | @@ -8895,7 +8894,7 @@ fn zirShl( |
| 8895 | 8894 | } |
| 8896 | 8895 | const int_info = scalar_ty.intInfo(target); |
| 8897 | 8896 | const truncated = try shifted.intTrunc(lhs_ty, sema.arena, int_info.signedness, int_info.bits, target); |
| 8898 | | if (truncated.compare(.eq, shifted, lhs_ty, sema.mod)) { |
| 8897 | if (try sema.compare(block, src, truncated, .eq, shifted, lhs_ty)) { |
| 8899 | 8898 | break :val shifted; |
| 8900 | 8899 | } |
| 8901 | 8900 | return sema.addConstUndef(lhs_ty); |
| ... | ... | @@ -8999,13 +8998,13 @@ fn zirShr( |
| 8999 | 8998 | return sema.addConstUndef(lhs_ty); |
| 9000 | 8999 | } |
| 9001 | 9000 | // If rhs is 0, return lhs without doing any calculations. |
| 9002 | | if (rhs_val.compareWithZero(.eq)) { |
| 9001 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9003 | 9002 | return sema.addConstant(lhs_ty, lhs_val); |
| 9004 | 9003 | } |
| 9005 | 9004 | if (air_tag == .shr_exact) { |
| 9006 | 9005 | // Detect if any ones would be shifted out. |
| 9007 | 9006 | const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target); |
| 9008 | | if (!truncated.compareWithZero(.eq)) { |
| 9007 | if (!(try truncated.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9009 | 9008 | return sema.addConstUndef(lhs_ty); |
| 9010 | 9009 | } |
| 9011 | 9010 | } |
| ... | ... | @@ -9015,7 +9014,7 @@ fn zirShr( |
| 9015 | 9014 | // Even if lhs is not comptime known, we can still deduce certain things based |
| 9016 | 9015 | // on rhs. |
| 9017 | 9016 | // If rhs is 0, return lhs without doing any calculations. |
| 9018 | | if (rhs_val.compareWithZero(.eq)) { |
| 9017 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9019 | 9018 | return lhs; |
| 9020 | 9019 | } |
| 9021 | 9020 | break :rs lhs_src; |
| ... | ... | @@ -9578,12 +9577,12 @@ fn zirOverflowArithmetic( |
| 9578 | 9577 | // to the result, even if it is undefined.. |
| 9579 | 9578 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 9580 | 9579 | if (maybe_lhs_val) |lhs_val| { |
| 9581 | | if (!lhs_val.isUndef() and lhs_val.compareWithZero(.eq)) { |
| 9580 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9582 | 9581 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 9583 | 9582 | } |
| 9584 | 9583 | } |
| 9585 | 9584 | if (maybe_rhs_val) |rhs_val| { |
| 9586 | | if (!rhs_val.isUndef() and rhs_val.compareWithZero(.eq)) { |
| 9585 | if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9587 | 9586 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9588 | 9587 | } |
| 9589 | 9588 | } |
| ... | ... | @@ -9593,7 +9592,7 @@ fn zirOverflowArithmetic( |
| 9593 | 9592 | break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) }; |
| 9594 | 9593 | } |
| 9595 | 9594 | |
| 9596 | | const result = try lhs_val.intAddWithOverflow(rhs_val, dest_ty, sema.arena, target); |
| 9595 | const result = try sema.intAddWithOverflow(block, src, lhs_val, rhs_val, dest_ty); |
| 9597 | 9596 | const overflowed = try sema.addConstant(overflowed_ty, result.overflowed); |
| 9598 | 9597 | const wrapped = try sema.addConstant(dest_ty, result.wrapped_result); |
| 9599 | 9598 | break :result .{ .overflowed = overflowed, .wrapped = wrapped }; |
| ... | ... | @@ -9606,14 +9605,14 @@ fn zirOverflowArithmetic( |
| 9606 | 9605 | if (maybe_rhs_val) |rhs_val| { |
| 9607 | 9606 | if (rhs_val.isUndef()) { |
| 9608 | 9607 | break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) }; |
| 9609 | | } else if (rhs_val.compareWithZero(.eq)) { |
| 9608 | } else if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9610 | 9609 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9611 | 9610 | } else if (maybe_lhs_val) |lhs_val| { |
| 9612 | 9611 | if (lhs_val.isUndef()) { |
| 9613 | 9612 | break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) }; |
| 9614 | 9613 | } |
| 9615 | 9614 | |
| 9616 | | const result = try lhs_val.intSubWithOverflow(rhs_val, dest_ty, sema.arena, target); |
| 9615 | const result = try sema.intSubWithOverflow(block, src, lhs_val, rhs_val, dest_ty); |
| 9617 | 9616 | const overflowed = try sema.addConstant(overflowed_ty, result.overflowed); |
| 9618 | 9617 | const wrapped = try sema.addConstant(dest_ty, result.wrapped_result); |
| 9619 | 9618 | break :result .{ .overflowed = overflowed, .wrapped = wrapped }; |
| ... | ... | @@ -9626,9 +9625,9 @@ fn zirOverflowArithmetic( |
| 9626 | 9625 | // Otherwise, if either of the arguments is undefined, both results are undefined. |
| 9627 | 9626 | if (maybe_lhs_val) |lhs_val| { |
| 9628 | 9627 | if (!lhs_val.isUndef()) { |
| 9629 | | if (lhs_val.compareWithZero(.eq)) { |
| 9628 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9630 | 9629 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9631 | | } else if (lhs_val.compare(.eq, Value.one, dest_ty, mod)) { |
| 9630 | } else if (try sema.compare(block, src, lhs_val, .eq, Value.one, dest_ty)) { |
| 9632 | 9631 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 9633 | 9632 | } |
| 9634 | 9633 | } |
| ... | ... | @@ -9636,9 +9635,9 @@ fn zirOverflowArithmetic( |
| 9636 | 9635 | |
| 9637 | 9636 | if (maybe_rhs_val) |rhs_val| { |
| 9638 | 9637 | if (!rhs_val.isUndef()) { |
| 9639 | | if (rhs_val.compareWithZero(.eq)) { |
| 9638 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9640 | 9639 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs }; |
| 9641 | | } else if (rhs_val.compare(.eq, Value.one, dest_ty, mod)) { |
| 9640 | } else if (try sema.compare(block, src, rhs_val, .eq, Value.one, dest_ty)) { |
| 9642 | 9641 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9643 | 9642 | } |
| 9644 | 9643 | } |
| ... | ... | @@ -9662,12 +9661,12 @@ fn zirOverflowArithmetic( |
| 9662 | 9661 | // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred. |
| 9663 | 9662 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 9664 | 9663 | if (maybe_lhs_val) |lhs_val| { |
| 9665 | | if (!lhs_val.isUndef() and lhs_val.compareWithZero(.eq)) { |
| 9664 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9666 | 9665 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9667 | 9666 | } |
| 9668 | 9667 | } |
| 9669 | 9668 | if (maybe_rhs_val) |rhs_val| { |
| 9670 | | if (!rhs_val.isUndef() and rhs_val.compareWithZero(.eq)) { |
| 9669 | if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9671 | 9670 | break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs }; |
| 9672 | 9671 | } |
| 9673 | 9672 | } |
| ... | ... | @@ -9815,7 +9814,7 @@ fn analyzeArithmetic( |
| 9815 | 9814 | // overflow (max_int), causing illegal behavior. |
| 9816 | 9815 | // For floats: either operand being undef makes the result undef. |
| 9817 | 9816 | if (maybe_lhs_val) |lhs_val| { |
| 9818 | | if (!lhs_val.isUndef() and lhs_val.compareWithZero(.eq)) { |
| 9817 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9819 | 9818 | return casted_rhs; |
| 9820 | 9819 | } |
| 9821 | 9820 | } |
| ... | ... | @@ -9827,7 +9826,7 @@ fn analyzeArithmetic( |
| 9827 | 9826 | return sema.addConstUndef(resolved_type); |
| 9828 | 9827 | } |
| 9829 | 9828 | } |
| 9830 | | if (rhs_val.compareWithZero(.eq)) { |
| 9829 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9831 | 9830 | return casted_lhs; |
| 9832 | 9831 | } |
| 9833 | 9832 | } |
| ... | ... | @@ -9841,15 +9840,15 @@ fn analyzeArithmetic( |
| 9841 | 9840 | } |
| 9842 | 9841 | if (maybe_rhs_val) |rhs_val| { |
| 9843 | 9842 | if (is_int) { |
| 9844 | | const sum = try lhs_val.intAdd(rhs_val, resolved_type, sema.arena, target); |
| 9845 | | if (!sum.intFitsInType(resolved_type, target)) { |
| 9843 | const sum = try sema.intAdd(block, src, lhs_val, rhs_val, resolved_type); |
| 9844 | if (!(try sema.intFitsInType(block, src, sum, resolved_type))) { |
| 9846 | 9845 | return sema.failWithIntegerOverflow(block, src, resolved_type, sum); |
| 9847 | 9846 | } |
| 9848 | 9847 | return sema.addConstant(resolved_type, sum); |
| 9849 | 9848 | } else { |
| 9850 | 9849 | return sema.addConstant( |
| 9851 | 9850 | resolved_type, |
| 9852 | | try lhs_val.floatAdd(rhs_val, resolved_type, sema.arena, target), |
| 9851 | try sema.floatAdd(lhs_val, rhs_val, resolved_type), |
| 9853 | 9852 | ); |
| 9854 | 9853 | } |
| 9855 | 9854 | } else break :rs .{ .src = rhs_src, .air_tag = .add }; |
| ... | ... | @@ -9860,7 +9859,7 @@ fn analyzeArithmetic( |
| 9860 | 9859 | // If either of the operands are zero, the other operand is returned. |
| 9861 | 9860 | // If either of the operands are undefined, the result is undefined. |
| 9862 | 9861 | if (maybe_lhs_val) |lhs_val| { |
| 9863 | | if (!lhs_val.isUndef() and lhs_val.compareWithZero(.eq)) { |
| 9862 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9864 | 9863 | return casted_rhs; |
| 9865 | 9864 | } |
| 9866 | 9865 | } |
| ... | ... | @@ -9868,13 +9867,13 @@ fn analyzeArithmetic( |
| 9868 | 9867 | if (rhs_val.isUndef()) { |
| 9869 | 9868 | return sema.addConstUndef(resolved_type); |
| 9870 | 9869 | } |
| 9871 | | if (rhs_val.compareWithZero(.eq)) { |
| 9870 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9872 | 9871 | return casted_lhs; |
| 9873 | 9872 | } |
| 9874 | 9873 | if (maybe_lhs_val) |lhs_val| { |
| 9875 | 9874 | return sema.addConstant( |
| 9876 | 9875 | resolved_type, |
| 9877 | | try lhs_val.numberAddWrap(rhs_val, resolved_type, sema.arena, target), |
| 9876 | try sema.numberAddWrap(block, src, lhs_val, rhs_val, resolved_type), |
| 9878 | 9877 | ); |
| 9879 | 9878 | } else break :rs .{ .src = lhs_src, .air_tag = .addwrap }; |
| 9880 | 9879 | } else break :rs .{ .src = rhs_src, .air_tag = .addwrap }; |
| ... | ... | @@ -9884,7 +9883,7 @@ fn analyzeArithmetic( |
| 9884 | 9883 | // If either of the operands are zero, then the other operand is returned. |
| 9885 | 9884 | // If either of the operands are undefined, the result is undefined. |
| 9886 | 9885 | if (maybe_lhs_val) |lhs_val| { |
| 9887 | | if (!lhs_val.isUndef() and lhs_val.compareWithZero(.eq)) { |
| 9886 | if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) { |
| 9888 | 9887 | return casted_rhs; |
| 9889 | 9888 | } |
| 9890 | 9889 | } |
| ... | ... | @@ -9892,12 +9891,12 @@ fn analyzeArithmetic( |
| 9892 | 9891 | if (rhs_val.isUndef()) { |
| 9893 | 9892 | return sema.addConstUndef(resolved_type); |
| 9894 | 9893 | } |
| 9895 | | if (rhs_val.compareWithZero(.eq)) { |
| 9894 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9896 | 9895 | return casted_lhs; |
| 9897 | 9896 | } |
| 9898 | 9897 | if (maybe_lhs_val) |lhs_val| { |
| 9899 | 9898 | const val = if (scalar_tag == .ComptimeInt) |
| 9900 | | try lhs_val.intAdd(rhs_val, resolved_type, sema.arena, target) |
| 9899 | try sema.intAdd(block, src, lhs_val, rhs_val, resolved_type) |
| 9901 | 9900 | else |
| 9902 | 9901 | try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, target); |
| 9903 | 9902 | |
| ... | ... | @@ -9921,7 +9920,7 @@ fn analyzeArithmetic( |
| 9921 | 9920 | return sema.addConstUndef(resolved_type); |
| 9922 | 9921 | } |
| 9923 | 9922 | } |
| 9924 | | if (rhs_val.compareWithZero(.eq)) { |
| 9923 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9925 | 9924 | return casted_lhs; |
| 9926 | 9925 | } |
| 9927 | 9926 | } |
| ... | ... | @@ -9935,15 +9934,15 @@ fn analyzeArithmetic( |
| 9935 | 9934 | } |
| 9936 | 9935 | if (maybe_rhs_val) |rhs_val| { |
| 9937 | 9936 | if (is_int) { |
| 9938 | | const diff = try lhs_val.intSub(rhs_val, resolved_type, sema.arena, target); |
| 9939 | | if (!diff.intFitsInType(resolved_type, target)) { |
| 9937 | const diff = try sema.intSub(block, src, lhs_val, rhs_val, resolved_type); |
| 9938 | if (!(try sema.intFitsInType(block, src, diff, resolved_type))) { |
| 9940 | 9939 | return sema.failWithIntegerOverflow(block, src, resolved_type, diff); |
| 9941 | 9940 | } |
| 9942 | 9941 | return sema.addConstant(resolved_type, diff); |
| 9943 | 9942 | } else { |
| 9944 | 9943 | return sema.addConstant( |
| 9945 | 9944 | resolved_type, |
| 9946 | | try lhs_val.floatSub(rhs_val, resolved_type, sema.arena, target), |
| 9945 | try sema.floatSub(lhs_val, rhs_val, resolved_type), |
| 9947 | 9946 | ); |
| 9948 | 9947 | } |
| 9949 | 9948 | } else break :rs .{ .src = rhs_src, .air_tag = .sub }; |
| ... | ... | @@ -9957,7 +9956,7 @@ fn analyzeArithmetic( |
| 9957 | 9956 | if (rhs_val.isUndef()) { |
| 9958 | 9957 | return sema.addConstUndef(resolved_type); |
| 9959 | 9958 | } |
| 9960 | | if (rhs_val.compareWithZero(.eq)) { |
| 9959 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9961 | 9960 | return casted_lhs; |
| 9962 | 9961 | } |
| 9963 | 9962 | } |
| ... | ... | @@ -9968,7 +9967,7 @@ fn analyzeArithmetic( |
| 9968 | 9967 | if (maybe_rhs_val) |rhs_val| { |
| 9969 | 9968 | return sema.addConstant( |
| 9970 | 9969 | resolved_type, |
| 9971 | | try lhs_val.numberSubWrap(rhs_val, resolved_type, sema.arena, target), |
| 9970 | try sema.numberSubWrap(block, src, lhs_val, rhs_val, resolved_type), |
| 9972 | 9971 | ); |
| 9973 | 9972 | } else break :rs .{ .src = rhs_src, .air_tag = .subwrap }; |
| 9974 | 9973 | } else break :rs .{ .src = lhs_src, .air_tag = .subwrap }; |
| ... | ... | @@ -9981,7 +9980,7 @@ fn analyzeArithmetic( |
| 9981 | 9980 | if (rhs_val.isUndef()) { |
| 9982 | 9981 | return sema.addConstUndef(resolved_type); |
| 9983 | 9982 | } |
| 9984 | | if (rhs_val.compareWithZero(.eq)) { |
| 9983 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 9985 | 9984 | return casted_lhs; |
| 9986 | 9985 | } |
| 9987 | 9986 | } |
| ... | ... | @@ -9991,7 +9990,7 @@ fn analyzeArithmetic( |
| 9991 | 9990 | } |
| 9992 | 9991 | if (maybe_rhs_val) |rhs_val| { |
| 9993 | 9992 | const val = if (scalar_tag == .ComptimeInt) |
| 9994 | | try lhs_val.intSub(rhs_val, resolved_type, sema.arena, target) |
| 9993 | try sema.intSub(block, src, lhs_val, rhs_val, resolved_type) |
| 9995 | 9994 | else |
| 9996 | 9995 | try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, target); |
| 9997 | 9996 | |
| ... | ... | @@ -10032,7 +10031,7 @@ fn analyzeArithmetic( |
| 10032 | 10031 | .Int, .ComptimeInt, .ComptimeFloat => { |
| 10033 | 10032 | if (maybe_lhs_val) |lhs_val| { |
| 10034 | 10033 | if (!lhs_val.isUndef()) { |
| 10035 | | if (lhs_val.compareWithZero(.eq)) { |
| 10034 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10036 | 10035 | return sema.addConstant(resolved_type, Value.zero); |
| 10037 | 10036 | } |
| 10038 | 10037 | } |
| ... | ... | @@ -10041,7 +10040,7 @@ fn analyzeArithmetic( |
| 10041 | 10040 | if (rhs_val.isUndef()) { |
| 10042 | 10041 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10043 | 10042 | } |
| 10044 | | if (rhs_val.compareWithZero(.eq)) { |
| 10043 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10045 | 10044 | return sema.failWithDivideByZero(block, rhs_src); |
| 10046 | 10045 | } |
| 10047 | 10046 | } |
| ... | ... | @@ -10053,7 +10052,7 @@ fn analyzeArithmetic( |
| 10053 | 10052 | if (lhs_val.isUndef()) { |
| 10054 | 10053 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 10055 | 10054 | if (maybe_rhs_val) |rhs_val| { |
| 10056 | | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { |
| 10055 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 10057 | 10056 | return sema.addConstUndef(resolved_type); |
| 10058 | 10057 | } |
| 10059 | 10058 | } |
| ... | ... | @@ -10111,7 +10110,7 @@ fn analyzeArithmetic( |
| 10111 | 10110 | // If the lhs is undefined, result is undefined. |
| 10112 | 10111 | if (maybe_lhs_val) |lhs_val| { |
| 10113 | 10112 | if (!lhs_val.isUndef()) { |
| 10114 | | if (lhs_val.compareWithZero(.eq)) { |
| 10113 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10115 | 10114 | return sema.addConstant(resolved_type, Value.zero); |
| 10116 | 10115 | } |
| 10117 | 10116 | } |
| ... | ... | @@ -10120,7 +10119,7 @@ fn analyzeArithmetic( |
| 10120 | 10119 | if (rhs_val.isUndef()) { |
| 10121 | 10120 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10122 | 10121 | } |
| 10123 | | if (rhs_val.compareWithZero(.eq)) { |
| 10122 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10124 | 10123 | return sema.failWithDivideByZero(block, rhs_src); |
| 10125 | 10124 | } |
| 10126 | 10125 | } |
| ... | ... | @@ -10128,7 +10127,7 @@ fn analyzeArithmetic( |
| 10128 | 10127 | if (lhs_val.isUndef()) { |
| 10129 | 10128 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 10130 | 10129 | if (maybe_rhs_val) |rhs_val| { |
| 10131 | | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { |
| 10130 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 10132 | 10131 | return sema.addConstUndef(resolved_type); |
| 10133 | 10132 | } |
| 10134 | 10133 | } |
| ... | ... | @@ -10174,7 +10173,7 @@ fn analyzeArithmetic( |
| 10174 | 10173 | // If the lhs is undefined, result is undefined. |
| 10175 | 10174 | if (maybe_lhs_val) |lhs_val| { |
| 10176 | 10175 | if (!lhs_val.isUndef()) { |
| 10177 | | if (lhs_val.compareWithZero(.eq)) { |
| 10176 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10178 | 10177 | return sema.addConstant(resolved_type, Value.zero); |
| 10179 | 10178 | } |
| 10180 | 10179 | } |
| ... | ... | @@ -10183,7 +10182,7 @@ fn analyzeArithmetic( |
| 10183 | 10182 | if (rhs_val.isUndef()) { |
| 10184 | 10183 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10185 | 10184 | } |
| 10186 | | if (rhs_val.compareWithZero(.eq)) { |
| 10185 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10187 | 10186 | return sema.failWithDivideByZero(block, rhs_src); |
| 10188 | 10187 | } |
| 10189 | 10188 | } |
| ... | ... | @@ -10191,7 +10190,7 @@ fn analyzeArithmetic( |
| 10191 | 10190 | if (lhs_val.isUndef()) { |
| 10192 | 10191 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 10193 | 10192 | if (maybe_rhs_val) |rhs_val| { |
| 10194 | | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { |
| 10193 | if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) { |
| 10195 | 10194 | return sema.addConstUndef(resolved_type); |
| 10196 | 10195 | } |
| 10197 | 10196 | } |
| ... | ... | @@ -10236,7 +10235,7 @@ fn analyzeArithmetic( |
| 10236 | 10235 | if (lhs_val.isUndef()) { |
| 10237 | 10236 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10238 | 10237 | } else { |
| 10239 | | if (lhs_val.compareWithZero(.eq)) { |
| 10238 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10240 | 10239 | return sema.addConstant(resolved_type, Value.zero); |
| 10241 | 10240 | } |
| 10242 | 10241 | } |
| ... | ... | @@ -10245,7 +10244,7 @@ fn analyzeArithmetic( |
| 10245 | 10244 | if (rhs_val.isUndef()) { |
| 10246 | 10245 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10247 | 10246 | } |
| 10248 | | if (rhs_val.compareWithZero(.eq)) { |
| 10247 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10249 | 10248 | return sema.failWithDivideByZero(block, rhs_src); |
| 10250 | 10249 | } |
| 10251 | 10250 | } |
| ... | ... | @@ -10278,10 +10277,10 @@ fn analyzeArithmetic( |
| 10278 | 10277 | // For floats: either operand being undef makes the result undef. |
| 10279 | 10278 | if (maybe_lhs_val) |lhs_val| { |
| 10280 | 10279 | if (!lhs_val.isUndef()) { |
| 10281 | | if (lhs_val.compareWithZero(.eq)) { |
| 10280 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10282 | 10281 | return sema.addConstant(resolved_type, Value.zero); |
| 10283 | 10282 | } |
| 10284 | | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10283 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 10285 | 10284 | return casted_rhs; |
| 10286 | 10285 | } |
| 10287 | 10286 | } |
| ... | ... | @@ -10294,10 +10293,10 @@ fn analyzeArithmetic( |
| 10294 | 10293 | return sema.addConstUndef(resolved_type); |
| 10295 | 10294 | } |
| 10296 | 10295 | } |
| 10297 | | if (rhs_val.compareWithZero(.eq)) { |
| 10296 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10298 | 10297 | return sema.addConstant(resolved_type, Value.zero); |
| 10299 | 10298 | } |
| 10300 | | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10299 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 10301 | 10300 | return casted_lhs; |
| 10302 | 10301 | } |
| 10303 | 10302 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10310,7 +10309,7 @@ fn analyzeArithmetic( |
| 10310 | 10309 | } |
| 10311 | 10310 | if (is_int) { |
| 10312 | 10311 | const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, target); |
| 10313 | | if (!product.intFitsInType(resolved_type, target)) { |
| 10312 | if (!(try sema.intFitsInType(block, src, product, resolved_type))) { |
| 10314 | 10313 | return sema.failWithIntegerOverflow(block, src, resolved_type, product); |
| 10315 | 10314 | } |
| 10316 | 10315 | return sema.addConstant(resolved_type, product); |
| ... | ... | @@ -10330,10 +10329,10 @@ fn analyzeArithmetic( |
| 10330 | 10329 | // If either of the operands are undefined, result is undefined. |
| 10331 | 10330 | if (maybe_lhs_val) |lhs_val| { |
| 10332 | 10331 | if (!lhs_val.isUndef()) { |
| 10333 | | if (lhs_val.compareWithZero(.eq)) { |
| 10332 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10334 | 10333 | return sema.addConstant(resolved_type, Value.zero); |
| 10335 | 10334 | } |
| 10336 | | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10335 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 10337 | 10336 | return casted_rhs; |
| 10338 | 10337 | } |
| 10339 | 10338 | } |
| ... | ... | @@ -10342,10 +10341,10 @@ fn analyzeArithmetic( |
| 10342 | 10341 | if (rhs_val.isUndef()) { |
| 10343 | 10342 | return sema.addConstUndef(resolved_type); |
| 10344 | 10343 | } |
| 10345 | | if (rhs_val.compareWithZero(.eq)) { |
| 10344 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10346 | 10345 | return sema.addConstant(resolved_type, Value.zero); |
| 10347 | 10346 | } |
| 10348 | | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10347 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 10349 | 10348 | return casted_lhs; |
| 10350 | 10349 | } |
| 10351 | 10350 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10366,10 +10365,10 @@ fn analyzeArithmetic( |
| 10366 | 10365 | // If either of the operands are undefined, result is undefined. |
| 10367 | 10366 | if (maybe_lhs_val) |lhs_val| { |
| 10368 | 10367 | if (!lhs_val.isUndef()) { |
| 10369 | | if (lhs_val.compareWithZero(.eq)) { |
| 10368 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10370 | 10369 | return sema.addConstant(resolved_type, Value.zero); |
| 10371 | 10370 | } |
| 10372 | | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10371 | if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) { |
| 10373 | 10372 | return casted_rhs; |
| 10374 | 10373 | } |
| 10375 | 10374 | } |
| ... | ... | @@ -10378,10 +10377,10 @@ fn analyzeArithmetic( |
| 10378 | 10377 | if (rhs_val.isUndef()) { |
| 10379 | 10378 | return sema.addConstUndef(resolved_type); |
| 10380 | 10379 | } |
| 10381 | | if (rhs_val.compareWithZero(.eq)) { |
| 10380 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10382 | 10381 | return sema.addConstant(resolved_type, Value.zero); |
| 10383 | 10382 | } |
| 10384 | | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { |
| 10383 | if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) { |
| 10385 | 10384 | return casted_lhs; |
| 10386 | 10385 | } |
| 10387 | 10386 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10417,7 +10416,7 @@ fn analyzeArithmetic( |
| 10417 | 10416 | if (lhs_val.isUndef()) { |
| 10418 | 10417 | return sema.failWithUseOfUndef(block, lhs_src); |
| 10419 | 10418 | } |
| 10420 | | if (lhs_val.compareWithZero(.eq)) { |
| 10419 | if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10421 | 10420 | return sema.addConstant(resolved_type, Value.zero); |
| 10422 | 10421 | } |
| 10423 | 10422 | } else if (lhs_scalar_ty.isSignedInt()) { |
| ... | ... | @@ -10427,23 +10426,23 @@ fn analyzeArithmetic( |
| 10427 | 10426 | if (rhs_val.isUndef()) { |
| 10428 | 10427 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10429 | 10428 | } |
| 10430 | | if (rhs_val.compareWithZero(.eq)) { |
| 10429 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10431 | 10430 | return sema.failWithDivideByZero(block, rhs_src); |
| 10432 | 10431 | } |
| 10433 | 10432 | if (maybe_lhs_val) |lhs_val| { |
| 10434 | 10433 | const rem_result = try lhs_val.intRem(rhs_val, resolved_type, sema.arena, target); |
| 10435 | 10434 | // If this answer could possibly be different by doing `intMod`, |
| 10436 | 10435 | // we must emit a compile error. Otherwise, it's OK. |
| 10437 | | if (rhs_val.compareWithZero(.lt) != lhs_val.compareWithZero(.lt) and |
| 10438 | | !rem_result.compareWithZero(.eq)) |
| 10436 | if ((try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) != (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) and |
| 10437 | !(try rem_result.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) |
| 10439 | 10438 | { |
| 10440 | | const bad_src = if (lhs_val.compareWithZero(.lt)) |
| 10439 | const bad_src = if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) |
| 10441 | 10440 | lhs_src |
| 10442 | 10441 | else |
| 10443 | 10442 | rhs_src; |
| 10444 | 10443 | return sema.failWithModRemNegative(block, bad_src, lhs_ty, rhs_ty); |
| 10445 | 10444 | } |
| 10446 | | if (lhs_val.compareWithZero(.lt)) { |
| 10445 | if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) { |
| 10447 | 10446 | // Negative |
| 10448 | 10447 | return sema.addConstant(resolved_type, Value.zero); |
| 10449 | 10448 | } |
| ... | ... | @@ -10461,14 +10460,14 @@ fn analyzeArithmetic( |
| 10461 | 10460 | if (rhs_val.isUndef()) { |
| 10462 | 10461 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10463 | 10462 | } |
| 10464 | | if (rhs_val.compareWithZero(.eq)) { |
| 10463 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10465 | 10464 | return sema.failWithDivideByZero(block, rhs_src); |
| 10466 | 10465 | } |
| 10467 | | if (rhs_val.compareWithZero(.lt)) { |
| 10466 | if (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) { |
| 10468 | 10467 | return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty); |
| 10469 | 10468 | } |
| 10470 | 10469 | if (maybe_lhs_val) |lhs_val| { |
| 10471 | | if (lhs_val.isUndef() or lhs_val.compareWithZero(.lt)) { |
| 10470 | if (lhs_val.isUndef() or (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))) { |
| 10472 | 10471 | return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty); |
| 10473 | 10472 | } |
| 10474 | 10473 | return sema.addConstant( |
| ... | ... | @@ -10504,7 +10503,7 @@ fn analyzeArithmetic( |
| 10504 | 10503 | if (rhs_val.isUndef()) { |
| 10505 | 10504 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10506 | 10505 | } |
| 10507 | | if (rhs_val.compareWithZero(.eq)) { |
| 10506 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10508 | 10507 | return sema.failWithDivideByZero(block, rhs_src); |
| 10509 | 10508 | } |
| 10510 | 10509 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10523,7 +10522,7 @@ fn analyzeArithmetic( |
| 10523 | 10522 | if (rhs_val.isUndef()) { |
| 10524 | 10523 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10525 | 10524 | } |
| 10526 | | if (rhs_val.compareWithZero(.eq)) { |
| 10525 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10527 | 10526 | return sema.failWithDivideByZero(block, rhs_src); |
| 10528 | 10527 | } |
| 10529 | 10528 | } |
| ... | ... | @@ -10561,7 +10560,7 @@ fn analyzeArithmetic( |
| 10561 | 10560 | if (rhs_val.isUndef()) { |
| 10562 | 10561 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10563 | 10562 | } |
| 10564 | | if (rhs_val.compareWithZero(.eq)) { |
| 10563 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10565 | 10564 | return sema.failWithDivideByZero(block, rhs_src); |
| 10566 | 10565 | } |
| 10567 | 10566 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10580,7 +10579,7 @@ fn analyzeArithmetic( |
| 10580 | 10579 | if (rhs_val.isUndef()) { |
| 10581 | 10580 | return sema.failWithUseOfUndef(block, rhs_src); |
| 10582 | 10581 | } |
| 10583 | | if (rhs_val.compareWithZero(.eq)) { |
| 10582 | if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) { |
| 10584 | 10583 | return sema.failWithDivideByZero(block, rhs_src); |
| 10585 | 10584 | } |
| 10586 | 10585 | } |
| ... | ... | @@ -11095,11 +11094,11 @@ fn cmpSelf( |
| 11095 | 11094 | |
| 11096 | 11095 | if (resolved_type.zigTypeTag() == .Vector) { |
| 11097 | 11096 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool"); |
| 11098 | | const cmp_val = try lhs_val.compareVector(op, rhs_val, resolved_type, sema.arena, sema.mod); |
| 11097 | const cmp_val = try sema.compareVector(block, lhs_src, lhs_val, op, rhs_val, resolved_type); |
| 11099 | 11098 | return sema.addConstant(result_ty, cmp_val); |
| 11100 | 11099 | } |
| 11101 | 11100 | |
| 11102 | | if (lhs_val.compare(op, rhs_val, resolved_type, sema.mod)) { |
| 11101 | if (try sema.compare(block, lhs_src, lhs_val, op, rhs_val, resolved_type)) { |
| 11103 | 11102 | return Air.Inst.Ref.bool_true; |
| 11104 | 11103 | } else { |
| 11105 | 11104 | return Air.Inst.Ref.bool_false; |
| ... | ... | @@ -11157,24 +11156,22 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 11157 | 11156 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 11158 | 11157 | const src = inst_data.src(); |
| 11159 | 11158 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 11160 | | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 11161 | | try sema.resolveTypeLayout(block, src, operand_ty); |
| 11162 | | const target = sema.mod.getTarget(); |
| 11163 | | const abi_size = switch (operand_ty.zigTypeTag()) { |
| 11159 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 11160 | switch (ty.zigTypeTag()) { |
| 11164 | 11161 | .Fn => unreachable, |
| 11165 | 11162 | .NoReturn, |
| 11166 | 11163 | .Undefined, |
| 11167 | 11164 | .Null, |
| 11168 | 11165 | .BoundFn, |
| 11169 | 11166 | .Opaque, |
| 11170 | | => return sema.fail(block, src, "no size available for type '{}'", .{operand_ty.fmt(sema.mod)}), |
| 11167 | => return sema.fail(block, src, "no size available for type '{}'", .{ty.fmt(sema.mod)}), |
| 11171 | 11168 | |
| 11172 | 11169 | .Type, |
| 11173 | 11170 | .EnumLiteral, |
| 11174 | 11171 | .ComptimeFloat, |
| 11175 | 11172 | .ComptimeInt, |
| 11176 | 11173 | .Void, |
| 11177 | | => 0, |
| 11174 | => return sema.addIntUnsigned(Type.comptime_int, 0), |
| 11178 | 11175 | |
| 11179 | 11176 | .Bool, |
| 11180 | 11177 | .Int, |
| ... | ... | @@ -11190,9 +11187,14 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 11190 | 11187 | .Vector, |
| 11191 | 11188 | .Frame, |
| 11192 | 11189 | .AnyFrame, |
| 11193 | | => operand_ty.abiSize(target), |
| 11194 | | }; |
| 11195 | | return sema.addIntUnsigned(Type.comptime_int, abi_size); |
| 11190 | => {}, |
| 11191 | } |
| 11192 | const target = sema.mod.getTarget(); |
| 11193 | const val = try ty.lazyAbiSize(target, sema.arena); |
| 11194 | if (val.tag() == .lazy_size) { |
| 11195 | try sema.queueFullTypeResolution(ty); |
| 11196 | } |
| 11197 | return sema.addConstant(Type.comptime_int, val); |
| 11196 | 11198 | } |
| 11197 | 11199 | |
| 11198 | 11200 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -11202,7 +11204,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 11202 | 11204 | const operand_ty = try sema.resolveTypeFields(block, operand_src, unresolved_operand_ty); |
| 11203 | 11205 | const target = sema.mod.getTarget(); |
| 11204 | 11206 | const bit_size = operand_ty.bitSize(target); |
| 11205 | | return sema.addIntUnsigned(Type.initTag(.comptime_int), bit_size); |
| 11207 | return sema.addIntUnsigned(Type.comptime_int, bit_size); |
| 11206 | 11208 | } |
| 11207 | 11209 | |
| 11208 | 11210 | fn zirThis( |
| ... | ... | @@ -13516,10 +13518,11 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13516 | 13518 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 13517 | 13519 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 13518 | 13520 | const target = sema.mod.getTarget(); |
| 13519 | | return sema.addConstant( |
| 13520 | | Type.comptime_int, |
| 13521 | | try ty.lazyAbiAlignment(target, sema.arena), |
| 13522 | | ); |
| 13521 | const val = try ty.lazyAbiAlignment(target, sema.arena); |
| 13522 | if (val.tag() == .lazy_align) { |
| 13523 | try sema.queueFullTypeResolution(ty); |
| 13524 | } |
| 13525 | return sema.addConstant(Type.comptime_int, val); |
| 13523 | 13526 | } |
| 13524 | 13527 | |
| 13525 | 13528 | fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -14362,16 +14365,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14362 | 14365 | try sema.checkFloatType(block, operand_src, operand_ty); |
| 14363 | 14366 | |
| 14364 | 14367 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { |
| 14365 | | const target = sema.mod.getTarget(); |
| 14366 | | const result_val = val.floatToInt(sema.arena, operand_ty, dest_ty, target) catch |err| switch (err) { |
| 14367 | | error.FloatCannotFit => { |
| 14368 | | return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ |
| 14369 | | @floor(val.toFloat(f64)), |
| 14370 | | dest_ty.fmt(sema.mod), |
| 14371 | | }); |
| 14372 | | }, |
| 14373 | | else => |e| return e, |
| 14374 | | }; |
| 14368 | const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty); |
| 14375 | 14369 | return sema.addConstant(dest_ty, result_val); |
| 14376 | 14370 | } |
| 14377 | 14371 | |
| ... | ... | @@ -15563,7 +15557,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15563 | 15557 | .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, target), |
| 15564 | 15558 | .Min => accum = accum.numberMin(elem_val, target), |
| 15565 | 15559 | .Max => accum = accum.numberMax(elem_val, target), |
| 15566 | | .Add => accum = try accum.numberAddWrap(elem_val, scalar_ty, sema.arena, target), |
| 15560 | .Add => accum = try sema.numberAddWrap(block, operand_src, accum, elem_val, scalar_ty), |
| 15567 | 15561 | .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, target), |
| 15568 | 15562 | } |
| 15569 | 15563 | } |
| ... | ... | @@ -15958,14 +15952,14 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 15958 | 15952 | const new_val = switch (op) { |
| 15959 | 15953 | // zig fmt: off |
| 15960 | 15954 | .Xchg => operand_val, |
| 15961 | | .Add => try stored_val.numberAddWrap(operand_val, elem_ty, sema.arena, target), |
| 15962 | | .Sub => try stored_val.numberSubWrap(operand_val, elem_ty, sema.arena, target), |
| 15963 | | .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, target), |
| 15964 | | .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, target), |
| 15965 | | .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, target), |
| 15966 | | .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, target), |
| 15967 | | .Max => stored_val.numberMax (operand_val, target), |
| 15968 | | .Min => stored_val.numberMin (operand_val, target), |
| 15955 | .Add => try sema.numberAddWrap(block, src, stored_val, operand_val, elem_ty), |
| 15956 | .Sub => try sema.numberSubWrap(block, src, stored_val, operand_val, elem_ty), |
| 15957 | .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, target), |
| 15958 | .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, target), |
| 15959 | .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, target), |
| 15960 | .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, target), |
| 15961 | .Max => stored_val.numberMax (operand_val, target), |
| 15962 | .Min => stored_val.numberMin (operand_val, target), |
| 15969 | 15963 | // zig fmt: on |
| 15970 | 15964 | }; |
| 15971 | 15965 | try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty); |
| ... | ... | @@ -16097,12 +16091,12 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16097 | 16091 | const args_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; |
| 16098 | 16092 | const call_src = inst_data.src(); |
| 16099 | 16093 | |
| 16100 | | const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index); |
| 16101 | | var func = sema.resolveInst(extra.data.callee); |
| 16102 | | const options = sema.resolveInst(extra.data.options); |
| 16103 | | const args = sema.resolveInst(extra.data.args); |
| 16094 | const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; |
| 16095 | var func = sema.resolveInst(extra.callee); |
| 16096 | const options = sema.resolveInst(extra.options); |
| 16097 | const args = sema.resolveInst(extra.args); |
| 16104 | 16098 | |
| 16105 | | const modifier: std.builtin.CallOptions.Modifier = modifier: { |
| 16099 | const wanted_modifier: std.builtin.CallOptions.Modifier = modifier: { |
| 16106 | 16100 | const call_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions"); |
| 16107 | 16101 | const coerced_options = try sema.coerce(block, call_options_ty, options, options_src); |
| 16108 | 16102 | |
| ... | ... | @@ -16118,6 +16112,41 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16118 | 16112 | break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier); |
| 16119 | 16113 | }; |
| 16120 | 16114 | |
| 16115 | const modifier: std.builtin.CallOptions.Modifier = switch (wanted_modifier) { |
| 16116 | // These can be upgraded to comptime or nosuspend calls. |
| 16117 | .auto, .never_tail, .no_async => m: { |
| 16118 | if (extra.flags.is_comptime) { |
| 16119 | break :m .compile_time; |
| 16120 | } |
| 16121 | if (extra.flags.is_nosuspend) { |
| 16122 | break :m .no_async; |
| 16123 | } |
| 16124 | break :m wanted_modifier; |
| 16125 | }, |
| 16126 | // These can be upgraded to comptime. nosuspend bit can be safely ignored. |
| 16127 | .always_tail, .always_inline, .compile_time => m: { |
| 16128 | if (extra.flags.is_comptime) { |
| 16129 | break :m .compile_time; |
| 16130 | } |
| 16131 | break :m wanted_modifier; |
| 16132 | }, |
| 16133 | .async_kw => m: { |
| 16134 | if (extra.flags.is_nosuspend) { |
| 16135 | return sema.fail(block, options_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{}); |
| 16136 | } |
| 16137 | if (extra.flags.is_comptime) { |
| 16138 | return sema.fail(block, options_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{}); |
| 16139 | } |
| 16140 | break :m wanted_modifier; |
| 16141 | }, |
| 16142 | .never_inline => m: { |
| 16143 | if (extra.flags.is_comptime) { |
| 16144 | return sema.fail(block, options_src, "modifier 'never_inline' cannot be used in combination with comptime function call", .{}); |
| 16145 | } |
| 16146 | break :m wanted_modifier; |
| 16147 | }, |
| 16148 | }; |
| 16149 | |
| 16121 | 16150 | const args_ty = sema.typeOf(args); |
| 16122 | 16151 | if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) { |
| 16123 | 16152 | return sema.fail(block, args_src, "expected a tuple, found {}", .{args_ty.fmt(sema.mod)}); |
| ... | ... | @@ -16141,8 +16170,8 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 16141 | 16170 | resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty); |
| 16142 | 16171 | } |
| 16143 | 16172 | } |
| 16144 | | |
| 16145 | | return sema.analyzeCall(block, func, func_src, call_src, modifier, false, resolved_args); |
| 16173 | const ensure_result_used = extra.flags.ensure_result_used; |
| 16174 | return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args); |
| 16146 | 16175 | } |
| 16147 | 16176 | |
| 16148 | 16177 | fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -18855,18 +18884,13 @@ fn coerce( |
| 18855 | 18884 | .{ val.fmtValue(inst_ty, sema.mod), dest_ty.fmt(sema.mod) }, |
| 18856 | 18885 | ); |
| 18857 | 18886 | } |
| 18858 | | const result_val = val.floatToInt(sema.arena, inst_ty, dest_ty, target) catch |err| switch (err) { |
| 18859 | | error.FloatCannotFit => { |
| 18860 | | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ @floor(val.toFloat(f64)), dest_ty.fmt(sema.mod) }); |
| 18861 | | }, |
| 18862 | | else => |e| return e, |
| 18863 | | }; |
| 18887 | const result_val = try sema.floatToInt(block, inst_src, val, inst_ty, dest_ty); |
| 18864 | 18888 | return try sema.addConstant(dest_ty, result_val); |
| 18865 | 18889 | }, |
| 18866 | 18890 | .Int, .ComptimeInt => { |
| 18867 | 18891 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 18868 | 18892 | // comptime known integer to other number |
| 18869 | | if (!val.intFitsInType(dest_ty, target)) { |
| 18893 | if (!(try sema.intFitsInType(block, inst_src, val, dest_ty))) { |
| 18870 | 18894 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) }); |
| 18871 | 18895 | } |
| 18872 | 18896 | return try sema.addConstant(dest_ty, val); |
| ... | ... | @@ -21058,7 +21082,7 @@ fn analyzeSlice( |
| 21058 | 21082 | sema.arena, |
| 21059 | 21083 | array_ty.arrayLenIncludingSentinel(), |
| 21060 | 21084 | ); |
| 21061 | | if (end_val.compare(.gt, len_s_val, Type.usize, mod)) { |
| 21085 | if (try sema.compare(block, src, end_val, .gt, len_s_val, Type.usize)) { |
| 21062 | 21086 | const sentinel_label: []const u8 = if (array_ty.sentinel() != null) |
| 21063 | 21087 | " +1 (sentinel)" |
| 21064 | 21088 | else |
| ... | ... | @@ -21098,7 +21122,7 @@ fn analyzeSlice( |
| 21098 | 21122 | .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel), |
| 21099 | 21123 | }; |
| 21100 | 21124 | const slice_len_val = Value.initPayload(&int_payload.base); |
| 21101 | | if (end_val.compare(.gt, slice_len_val, Type.usize, mod)) { |
| 21125 | if (try sema.compare(block, src, end_val, .gt, slice_len_val, Type.usize)) { |
| 21102 | 21126 | const sentinel_label: []const u8 = if (has_sentinel) |
| 21103 | 21127 | " +1 (sentinel)" |
| 21104 | 21128 | else |
| ... | ... | @@ -21156,7 +21180,7 @@ fn analyzeSlice( |
| 21156 | 21180 | // requirement: start <= end |
| 21157 | 21181 | if (try sema.resolveDefinedValue(block, src, end)) |end_val| { |
| 21158 | 21182 | if (try sema.resolveDefinedValue(block, src, start)) |start_val| { |
| 21159 | | if (start_val.compare(.gt, end_val, Type.usize, mod)) { |
| 21183 | if (try sema.compare(block, src, start_val, .gt, end_val, Type.usize)) { |
| 21160 | 21184 | return sema.fail( |
| 21161 | 21185 | block, |
| 21162 | 21186 | start_src, |
| ... | ... | @@ -21364,11 +21388,11 @@ fn cmpNumeric( |
| 21364 | 21388 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, |
| 21365 | 21389 | // add/subtract 1. |
| 21366 | 21390 | const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| |
| 21367 | | lhs_val.compareWithZero(.lt) |
| 21391 | (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) |
| 21368 | 21392 | else |
| 21369 | 21393 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt()); |
| 21370 | 21394 | const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| |
| 21371 | | rhs_val.compareWithZero(.lt) |
| 21395 | (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) |
| 21372 | 21396 | else |
| 21373 | 21397 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt()); |
| 21374 | 21398 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; |
| ... | ... | @@ -21506,7 +21530,7 @@ fn cmpVector( |
| 21506 | 21530 | if (lhs_val.isUndef() or rhs_val.isUndef()) { |
| 21507 | 21531 | return sema.addConstUndef(result_ty); |
| 21508 | 21532 | } |
| 21509 | | const cmp_val = try lhs_val.compareVector(op, rhs_val, lhs_ty, sema.arena, sema.mod); |
| 21533 | const cmp_val = try sema.compareVector(block, src, lhs_val, op, rhs_val, lhs_ty); |
| 21510 | 21534 | return sema.addConstant(result_ty, cmp_val); |
| 21511 | 21535 | } else { |
| 21512 | 21536 | break :src rhs_src; |
| ... | ... | @@ -22869,8 +22893,6 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22869 | 22893 | enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields; |
| 22870 | 22894 | } |
| 22871 | 22895 | |
| 22872 | | const target = sema.mod.getTarget(); |
| 22873 | | |
| 22874 | 22896 | const bits_per_field = 4; |
| 22875 | 22897 | const fields_per_u32 = 32 / bits_per_field; |
| 22876 | 22898 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; |
| ... | ... | @@ -22934,7 +22956,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22934 | 22956 | }); |
| 22935 | 22957 | } else { |
| 22936 | 22958 | const val = if (last_tag_val) |val| |
| 22937 | | try val.intAdd(Value.one, int_tag_ty, sema.arena, target) |
| 22959 | try sema.intAdd(block, src, val, Value.one, int_tag_ty) |
| 22938 | 22960 | else |
| 22939 | 22961 | Value.zero; |
| 22940 | 22962 | last_tag_val = val; |
| ... | ... | @@ -24084,3 +24106,707 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { |
| 24084 | 24106 | const inst_ref = try sema.addType(ty); |
| 24085 | 24107 | try sema.types_to_resolve.append(sema.gpa, inst_ref); |
| 24086 | 24108 | } |
| 24109 | |
| 24110 | fn intAdd(sema: *Sema, block: *Block, src: LazySrcLoc, lhs: Value, rhs: Value, ty: Type) !Value { |
| 24111 | if (ty.zigTypeTag() == .Vector) { |
| 24112 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24113 | for (result_data) |*scalar, i| { |
| 24114 | scalar.* = try sema.intAddScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i)); |
| 24115 | } |
| 24116 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24117 | } |
| 24118 | return sema.intAddScalar(block, src, lhs, rhs); |
| 24119 | } |
| 24120 | |
| 24121 | fn intAddScalar(sema: *Sema, block: *Block, src: LazySrcLoc, lhs: Value, rhs: Value) !Value { |
| 24122 | // TODO is this a performance issue? maybe we should try the operation without |
| 24123 | // resorting to BigInt first. |
| 24124 | var lhs_space: Value.BigIntSpace = undefined; |
| 24125 | var rhs_space: Value.BigIntSpace = undefined; |
| 24126 | const target = sema.mod.getTarget(); |
| 24127 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, src)); |
| 24128 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, src)); |
| 24129 | const limbs = try sema.arena.alloc( |
| 24130 | std.math.big.Limb, |
| 24131 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, |
| 24132 | ); |
| 24133 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 24134 | result_bigint.add(lhs_bigint, rhs_bigint); |
| 24135 | return Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 24136 | } |
| 24137 | |
| 24138 | /// Supports both (vectors of) floats and ints; handles undefined scalars. |
| 24139 | fn numberAddWrap( |
| 24140 | sema: *Sema, |
| 24141 | block: *Block, |
| 24142 | src: LazySrcLoc, |
| 24143 | lhs: Value, |
| 24144 | rhs: Value, |
| 24145 | ty: Type, |
| 24146 | ) !Value { |
| 24147 | if (ty.zigTypeTag() == .Vector) { |
| 24148 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24149 | for (result_data) |*scalar, i| { |
| 24150 | scalar.* = try sema.numberAddWrapScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType()); |
| 24151 | } |
| 24152 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24153 | } |
| 24154 | return sema.numberAddWrapScalar(block, src, lhs, rhs, ty); |
| 24155 | } |
| 24156 | |
| 24157 | /// Supports both floats and ints; handles undefined. |
| 24158 | fn numberAddWrapScalar( |
| 24159 | sema: *Sema, |
| 24160 | block: *Block, |
| 24161 | src: LazySrcLoc, |
| 24162 | lhs: Value, |
| 24163 | rhs: Value, |
| 24164 | ty: Type, |
| 24165 | ) !Value { |
| 24166 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 24167 | |
| 24168 | if (ty.zigTypeTag() == .ComptimeInt) { |
| 24169 | return sema.intAdd(block, src, lhs, rhs, ty); |
| 24170 | } |
| 24171 | |
| 24172 | if (ty.isAnyFloat()) { |
| 24173 | return sema.floatAdd(lhs, rhs, ty); |
| 24174 | } |
| 24175 | |
| 24176 | const overflow_result = try sema.intAddWithOverflow(block, src, lhs, rhs, ty); |
| 24177 | return overflow_result.wrapped_result; |
| 24178 | } |
| 24179 | |
| 24180 | fn intSub( |
| 24181 | sema: *Sema, |
| 24182 | block: *Block, |
| 24183 | src: LazySrcLoc, |
| 24184 | lhs: Value, |
| 24185 | rhs: Value, |
| 24186 | ty: Type, |
| 24187 | ) !Value { |
| 24188 | if (ty.zigTypeTag() == .Vector) { |
| 24189 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24190 | for (result_data) |*scalar, i| { |
| 24191 | scalar.* = try sema.intSubScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i)); |
| 24192 | } |
| 24193 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24194 | } |
| 24195 | return sema.intSubScalar(block, src, lhs, rhs); |
| 24196 | } |
| 24197 | |
| 24198 | fn intSubScalar(sema: *Sema, block: *Block, src: LazySrcLoc, lhs: Value, rhs: Value) !Value { |
| 24199 | // TODO is this a performance issue? maybe we should try the operation without |
| 24200 | // resorting to BigInt first. |
| 24201 | var lhs_space: Value.BigIntSpace = undefined; |
| 24202 | var rhs_space: Value.BigIntSpace = undefined; |
| 24203 | const target = sema.mod.getTarget(); |
| 24204 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, src)); |
| 24205 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, src)); |
| 24206 | const limbs = try sema.arena.alloc( |
| 24207 | std.math.big.Limb, |
| 24208 | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1, |
| 24209 | ); |
| 24210 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 24211 | result_bigint.sub(lhs_bigint, rhs_bigint); |
| 24212 | return Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 24213 | } |
| 24214 | |
| 24215 | /// Supports both (vectors of) floats and ints; handles undefined scalars. |
| 24216 | fn numberSubWrap( |
| 24217 | sema: *Sema, |
| 24218 | block: *Block, |
| 24219 | src: LazySrcLoc, |
| 24220 | lhs: Value, |
| 24221 | rhs: Value, |
| 24222 | ty: Type, |
| 24223 | ) !Value { |
| 24224 | if (ty.zigTypeTag() == .Vector) { |
| 24225 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24226 | for (result_data) |*scalar, i| { |
| 24227 | scalar.* = try sema.numberSubWrapScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType()); |
| 24228 | } |
| 24229 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24230 | } |
| 24231 | return sema.numberSubWrapScalar(block, src, lhs, rhs, ty); |
| 24232 | } |
| 24233 | |
| 24234 | /// Supports both floats and ints; handles undefined. |
| 24235 | fn numberSubWrapScalar( |
| 24236 | sema: *Sema, |
| 24237 | block: *Block, |
| 24238 | src: LazySrcLoc, |
| 24239 | lhs: Value, |
| 24240 | rhs: Value, |
| 24241 | ty: Type, |
| 24242 | ) !Value { |
| 24243 | if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
| 24244 | |
| 24245 | if (ty.zigTypeTag() == .ComptimeInt) { |
| 24246 | return sema.intSub(block, src, lhs, rhs, ty); |
| 24247 | } |
| 24248 | |
| 24249 | if (ty.isAnyFloat()) { |
| 24250 | return sema.floatSub(lhs, rhs, ty); |
| 24251 | } |
| 24252 | |
| 24253 | const overflow_result = try sema.intSubWithOverflow(block, src, lhs, rhs, ty); |
| 24254 | return overflow_result.wrapped_result; |
| 24255 | } |
| 24256 | |
| 24257 | fn floatAdd( |
| 24258 | sema: *Sema, |
| 24259 | lhs: Value, |
| 24260 | rhs: Value, |
| 24261 | float_type: Type, |
| 24262 | ) !Value { |
| 24263 | if (float_type.zigTypeTag() == .Vector) { |
| 24264 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); |
| 24265 | for (result_data) |*scalar, i| { |
| 24266 | scalar.* = try sema.floatAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType()); |
| 24267 | } |
| 24268 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24269 | } |
| 24270 | return sema.floatAddScalar(lhs, rhs, float_type); |
| 24271 | } |
| 24272 | |
| 24273 | fn floatAddScalar( |
| 24274 | sema: *Sema, |
| 24275 | lhs: Value, |
| 24276 | rhs: Value, |
| 24277 | float_type: Type, |
| 24278 | ) !Value { |
| 24279 | const target = sema.mod.getTarget(); |
| 24280 | switch (float_type.floatBits(target)) { |
| 24281 | 16 => { |
| 24282 | const lhs_val = lhs.toFloat(f16); |
| 24283 | const rhs_val = rhs.toFloat(f16); |
| 24284 | return Value.Tag.float_16.create(sema.arena, lhs_val + rhs_val); |
| 24285 | }, |
| 24286 | 32 => { |
| 24287 | const lhs_val = lhs.toFloat(f32); |
| 24288 | const rhs_val = rhs.toFloat(f32); |
| 24289 | return Value.Tag.float_32.create(sema.arena, lhs_val + rhs_val); |
| 24290 | }, |
| 24291 | 64 => { |
| 24292 | const lhs_val = lhs.toFloat(f64); |
| 24293 | const rhs_val = rhs.toFloat(f64); |
| 24294 | return Value.Tag.float_64.create(sema.arena, lhs_val + rhs_val); |
| 24295 | }, |
| 24296 | 80 => { |
| 24297 | const lhs_val = lhs.toFloat(f80); |
| 24298 | const rhs_val = rhs.toFloat(f80); |
| 24299 | return Value.Tag.float_80.create(sema.arena, lhs_val + rhs_val); |
| 24300 | }, |
| 24301 | 128 => { |
| 24302 | const lhs_val = lhs.toFloat(f128); |
| 24303 | const rhs_val = rhs.toFloat(f128); |
| 24304 | return Value.Tag.float_128.create(sema.arena, lhs_val + rhs_val); |
| 24305 | }, |
| 24306 | else => unreachable, |
| 24307 | } |
| 24308 | } |
| 24309 | |
| 24310 | fn floatSub( |
| 24311 | sema: *Sema, |
| 24312 | lhs: Value, |
| 24313 | rhs: Value, |
| 24314 | float_type: Type, |
| 24315 | ) !Value { |
| 24316 | if (float_type.zigTypeTag() == .Vector) { |
| 24317 | const result_data = try sema.arena.alloc(Value, float_type.vectorLen()); |
| 24318 | for (result_data) |*scalar, i| { |
| 24319 | scalar.* = try sema.floatSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType()); |
| 24320 | } |
| 24321 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24322 | } |
| 24323 | return sema.floatSubScalar(lhs, rhs, float_type); |
| 24324 | } |
| 24325 | |
| 24326 | fn floatSubScalar( |
| 24327 | sema: *Sema, |
| 24328 | lhs: Value, |
| 24329 | rhs: Value, |
| 24330 | float_type: Type, |
| 24331 | ) !Value { |
| 24332 | const target = sema.mod.getTarget(); |
| 24333 | switch (float_type.floatBits(target)) { |
| 24334 | 16 => { |
| 24335 | const lhs_val = lhs.toFloat(f16); |
| 24336 | const rhs_val = rhs.toFloat(f16); |
| 24337 | return Value.Tag.float_16.create(sema.arena, lhs_val - rhs_val); |
| 24338 | }, |
| 24339 | 32 => { |
| 24340 | const lhs_val = lhs.toFloat(f32); |
| 24341 | const rhs_val = rhs.toFloat(f32); |
| 24342 | return Value.Tag.float_32.create(sema.arena, lhs_val - rhs_val); |
| 24343 | }, |
| 24344 | 64 => { |
| 24345 | const lhs_val = lhs.toFloat(f64); |
| 24346 | const rhs_val = rhs.toFloat(f64); |
| 24347 | return Value.Tag.float_64.create(sema.arena, lhs_val - rhs_val); |
| 24348 | }, |
| 24349 | 80 => { |
| 24350 | const lhs_val = lhs.toFloat(f80); |
| 24351 | const rhs_val = rhs.toFloat(f80); |
| 24352 | return Value.Tag.float_80.create(sema.arena, lhs_val - rhs_val); |
| 24353 | }, |
| 24354 | 128 => { |
| 24355 | const lhs_val = lhs.toFloat(f128); |
| 24356 | const rhs_val = rhs.toFloat(f128); |
| 24357 | return Value.Tag.float_128.create(sema.arena, lhs_val - rhs_val); |
| 24358 | }, |
| 24359 | else => unreachable, |
| 24360 | } |
| 24361 | } |
| 24362 | |
| 24363 | fn intSubWithOverflow( |
| 24364 | sema: *Sema, |
| 24365 | block: *Block, |
| 24366 | src: LazySrcLoc, |
| 24367 | lhs: Value, |
| 24368 | rhs: Value, |
| 24369 | ty: Type, |
| 24370 | ) !Value.OverflowArithmeticResult { |
| 24371 | if (ty.zigTypeTag() == .Vector) { |
| 24372 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24373 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24374 | for (result_data) |*scalar, i| { |
| 24375 | const of_math_result = try sema.intSubWithOverflowScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType()); |
| 24376 | overflowed_data[i] = of_math_result.overflowed; |
| 24377 | scalar.* = of_math_result.wrapped_result; |
| 24378 | } |
| 24379 | return Value.OverflowArithmeticResult{ |
| 24380 | .overflowed = try Value.Tag.aggregate.create(sema.arena, overflowed_data), |
| 24381 | .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data), |
| 24382 | }; |
| 24383 | } |
| 24384 | return sema.intSubWithOverflowScalar(block, src, lhs, rhs, ty); |
| 24385 | } |
| 24386 | |
| 24387 | fn intSubWithOverflowScalar( |
| 24388 | sema: *Sema, |
| 24389 | block: *Block, |
| 24390 | src: LazySrcLoc, |
| 24391 | lhs: Value, |
| 24392 | rhs: Value, |
| 24393 | ty: Type, |
| 24394 | ) !Value.OverflowArithmeticResult { |
| 24395 | const target = sema.mod.getTarget(); |
| 24396 | const info = ty.intInfo(target); |
| 24397 | |
| 24398 | var lhs_space: Value.BigIntSpace = undefined; |
| 24399 | var rhs_space: Value.BigIntSpace = undefined; |
| 24400 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, src)); |
| 24401 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, src)); |
| 24402 | const limbs = try sema.arena.alloc( |
| 24403 | std.math.big.Limb, |
| 24404 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 24405 | ); |
| 24406 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 24407 | const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 24408 | const wrapped_result = try Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 24409 | return Value.OverflowArithmeticResult{ |
| 24410 | .overflowed = Value.makeBool(overflowed), |
| 24411 | .wrapped_result = wrapped_result, |
| 24412 | }; |
| 24413 | } |
| 24414 | |
| 24415 | fn floatToInt( |
| 24416 | sema: *Sema, |
| 24417 | block: *Block, |
| 24418 | src: LazySrcLoc, |
| 24419 | val: Value, |
| 24420 | float_ty: Type, |
| 24421 | int_ty: Type, |
| 24422 | ) CompileError!Value { |
| 24423 | if (float_ty.zigTypeTag() == .Vector) { |
| 24424 | const elem_ty = float_ty.childType(); |
| 24425 | const result_data = try sema.arena.alloc(Value, float_ty.vectorLen()); |
| 24426 | for (result_data) |*scalar, i| { |
| 24427 | scalar.* = try sema.floatToIntScalar(block, src, val.indexVectorlike(i), elem_ty, int_ty.scalarType()); |
| 24428 | } |
| 24429 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24430 | } |
| 24431 | return sema.floatToIntScalar(block, src, val, float_ty, int_ty); |
| 24432 | } |
| 24433 | |
| 24434 | fn floatToIntScalar( |
| 24435 | sema: *Sema, |
| 24436 | block: *Block, |
| 24437 | src: LazySrcLoc, |
| 24438 | val: Value, |
| 24439 | float_ty: Type, |
| 24440 | int_ty: Type, |
| 24441 | ) CompileError!Value { |
| 24442 | const Limb = std.math.big.Limb; |
| 24443 | |
| 24444 | const float = val.toFloat(f128); |
| 24445 | if (std.math.isNan(float)) { |
| 24446 | return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{ |
| 24447 | int_ty.fmt(sema.mod), |
| 24448 | }); |
| 24449 | } |
| 24450 | if (std.math.isInf(float)) { |
| 24451 | return sema.fail(block, src, "float value Inf cannot be stored in integer type '{}'", .{ |
| 24452 | int_ty.fmt(sema.mod), |
| 24453 | }); |
| 24454 | } |
| 24455 | |
| 24456 | const is_negative = std.math.signbit(float); |
| 24457 | const floored = @floor(@fabs(float)); |
| 24458 | |
| 24459 | var rational = try std.math.big.Rational.init(sema.arena); |
| 24460 | defer rational.deinit(); |
| 24461 | rational.setFloat(f128, floored) catch |err| switch (err) { |
| 24462 | error.NonFiniteFloat => unreachable, |
| 24463 | error.OutOfMemory => return error.OutOfMemory, |
| 24464 | }; |
| 24465 | |
| 24466 | // The float is reduced in rational.setFloat, so we assert that denominator is equal to one |
| 24467 | const big_one = std.math.big.int.Const{ .limbs = &.{1}, .positive = true }; |
| 24468 | assert(rational.q.toConst().eqAbs(big_one)); |
| 24469 | |
| 24470 | const result_limbs = try sema.arena.dupe(Limb, rational.p.toConst().limbs); |
| 24471 | const result = if (is_negative) |
| 24472 | try Value.Tag.int_big_negative.create(sema.arena, result_limbs) |
| 24473 | else |
| 24474 | try Value.Tag.int_big_positive.create(sema.arena, result_limbs); |
| 24475 | |
| 24476 | if (!(try sema.intFitsInType(block, src, result, int_ty))) { |
| 24477 | return sema.fail(block, src, "float value {} cannot be stored in integer type '{}'", .{ |
| 24478 | val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod), |
| 24479 | }); |
| 24480 | } |
| 24481 | return result; |
| 24482 | } |
| 24483 | |
| 24484 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. |
| 24485 | /// Vectors are also accepted. Vector results are reduced with AND. |
| 24486 | fn intFitsInType( |
| 24487 | sema: *Sema, |
| 24488 | block: *Block, |
| 24489 | src: LazySrcLoc, |
| 24490 | self: Value, |
| 24491 | ty: Type, |
| 24492 | ) CompileError!bool { |
| 24493 | const target = sema.mod.getTarget(); |
| 24494 | switch (self.tag()) { |
| 24495 | .zero, |
| 24496 | .undef, |
| 24497 | .bool_false, |
| 24498 | => return true, |
| 24499 | |
| 24500 | .one, |
| 24501 | .bool_true, |
| 24502 | => switch (ty.zigTypeTag()) { |
| 24503 | .Int => { |
| 24504 | const info = ty.intInfo(target); |
| 24505 | return switch (info.signedness) { |
| 24506 | .signed => info.bits >= 2, |
| 24507 | .unsigned => info.bits >= 1, |
| 24508 | }; |
| 24509 | }, |
| 24510 | .ComptimeInt => return true, |
| 24511 | else => unreachable, |
| 24512 | }, |
| 24513 | |
| 24514 | .lazy_align => { |
| 24515 | const info = ty.intInfo(target); |
| 24516 | const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed); |
| 24517 | // If it is u16 or bigger we know the alignment fits without resolving it. |
| 24518 | if (info.bits >= max_needed_bits) return true; |
| 24519 | const x = try sema.typeAbiAlignment(block, src, self.castTag(.lazy_align).?.data); |
| 24520 | if (x == 0) return true; |
| 24521 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 24522 | return info.bits >= actual_needed_bits; |
| 24523 | }, |
| 24524 | .lazy_size => { |
| 24525 | const info = ty.intInfo(target); |
| 24526 | const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed); |
| 24527 | // If it is u64 or bigger we know the size fits without resolving it. |
| 24528 | if (info.bits >= max_needed_bits) return true; |
| 24529 | const x = try sema.typeAbiSize(block, src, self.castTag(.lazy_size).?.data); |
| 24530 | if (x == 0) return true; |
| 24531 | const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 24532 | return info.bits >= actual_needed_bits; |
| 24533 | }, |
| 24534 | |
| 24535 | .int_u64 => switch (ty.zigTypeTag()) { |
| 24536 | .Int => { |
| 24537 | const x = self.castTag(.int_u64).?.data; |
| 24538 | if (x == 0) return true; |
| 24539 | const info = ty.intInfo(target); |
| 24540 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed); |
| 24541 | return info.bits >= needed_bits; |
| 24542 | }, |
| 24543 | .ComptimeInt => return true, |
| 24544 | else => unreachable, |
| 24545 | }, |
| 24546 | .int_i64 => switch (ty.zigTypeTag()) { |
| 24547 | .Int => { |
| 24548 | const x = self.castTag(.int_i64).?.data; |
| 24549 | if (x == 0) return true; |
| 24550 | const info = ty.intInfo(target); |
| 24551 | if (info.signedness == .unsigned and x < 0) |
| 24552 | return false; |
| 24553 | var buffer: Value.BigIntSpace = undefined; |
| 24554 | return (try self.toBigIntAdvanced(&buffer, target, sema.kit(block, src))).fitsInTwosComp(info.signedness, info.bits); |
| 24555 | }, |
| 24556 | .ComptimeInt => return true, |
| 24557 | else => unreachable, |
| 24558 | }, |
| 24559 | .int_big_positive => switch (ty.zigTypeTag()) { |
| 24560 | .Int => { |
| 24561 | const info = ty.intInfo(target); |
| 24562 | return self.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 24563 | }, |
| 24564 | .ComptimeInt => return true, |
| 24565 | else => unreachable, |
| 24566 | }, |
| 24567 | .int_big_negative => switch (ty.zigTypeTag()) { |
| 24568 | .Int => { |
| 24569 | const info = ty.intInfo(target); |
| 24570 | return self.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits); |
| 24571 | }, |
| 24572 | .ComptimeInt => return true, |
| 24573 | else => unreachable, |
| 24574 | }, |
| 24575 | |
| 24576 | .the_only_possible_value => { |
| 24577 | assert(ty.intInfo(target).bits == 0); |
| 24578 | return true; |
| 24579 | }, |
| 24580 | |
| 24581 | .decl_ref_mut, |
| 24582 | .extern_fn, |
| 24583 | .decl_ref, |
| 24584 | .function, |
| 24585 | .variable, |
| 24586 | => switch (ty.zigTypeTag()) { |
| 24587 | .Int => { |
| 24588 | const info = ty.intInfo(target); |
| 24589 | const ptr_bits = target.cpu.arch.ptrBitWidth(); |
| 24590 | return switch (info.signedness) { |
| 24591 | .signed => info.bits > ptr_bits, |
| 24592 | .unsigned => info.bits >= ptr_bits, |
| 24593 | }; |
| 24594 | }, |
| 24595 | .ComptimeInt => return true, |
| 24596 | else => unreachable, |
| 24597 | }, |
| 24598 | |
| 24599 | .aggregate => { |
| 24600 | assert(ty.zigTypeTag() == .Vector); |
| 24601 | for (self.castTag(.aggregate).?.data) |elem| { |
| 24602 | if (!(try sema.intFitsInType(block, src, elem, ty.scalarType()))) { |
| 24603 | return false; |
| 24604 | } |
| 24605 | } |
| 24606 | return true; |
| 24607 | }, |
| 24608 | |
| 24609 | else => unreachable, |
| 24610 | } |
| 24611 | } |
| 24612 | |
| 24613 | fn intInRange( |
| 24614 | sema: *Sema, |
| 24615 | block: *Block, |
| 24616 | src: LazySrcLoc, |
| 24617 | tag_ty: Type, |
| 24618 | int_val: Value, |
| 24619 | end: usize, |
| 24620 | ) !bool { |
| 24621 | if (try int_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) return false; |
| 24622 | var end_payload: Value.Payload.U64 = .{ |
| 24623 | .base = .{ .tag = .int_u64 }, |
| 24624 | .data = end, |
| 24625 | }; |
| 24626 | const end_val = Value.initPayload(&end_payload.base); |
| 24627 | if (try sema.compare(block, src, int_val, .gte, end_val, tag_ty)) return false; |
| 24628 | return true; |
| 24629 | } |
| 24630 | |
| 24631 | /// Asserts the type is an enum. |
| 24632 | fn enumHasInt( |
| 24633 | sema: *Sema, |
| 24634 | block: *Block, |
| 24635 | src: LazySrcLoc, |
| 24636 | ty: Type, |
| 24637 | int: Value, |
| 24638 | ) CompileError!bool { |
| 24639 | switch (ty.tag()) { |
| 24640 | .enum_nonexhaustive => return sema.intFitsInType(block, src, int, ty), |
| 24641 | .enum_full => { |
| 24642 | const enum_full = ty.castTag(.enum_full).?.data; |
| 24643 | const tag_ty = enum_full.tag_ty; |
| 24644 | if (enum_full.values.count() == 0) { |
| 24645 | return intInRange(sema, block, src, tag_ty, int, enum_full.fields.count()); |
| 24646 | } else { |
| 24647 | return enum_full.values.containsContext(int, .{ |
| 24648 | .ty = tag_ty, |
| 24649 | .mod = sema.mod, |
| 24650 | }); |
| 24651 | } |
| 24652 | }, |
| 24653 | .enum_numbered => { |
| 24654 | const enum_obj = ty.castTag(.enum_numbered).?.data; |
| 24655 | const tag_ty = enum_obj.tag_ty; |
| 24656 | if (enum_obj.values.count() == 0) { |
| 24657 | return intInRange(sema, block, src, tag_ty, int, enum_obj.fields.count()); |
| 24658 | } else { |
| 24659 | return enum_obj.values.containsContext(int, .{ |
| 24660 | .ty = tag_ty, |
| 24661 | .mod = sema.mod, |
| 24662 | }); |
| 24663 | } |
| 24664 | }, |
| 24665 | .enum_simple => { |
| 24666 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 24667 | const fields_len = enum_simple.fields.count(); |
| 24668 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 24669 | var buffer: Type.Payload.Bits = .{ |
| 24670 | .base = .{ .tag = .int_unsigned }, |
| 24671 | .data = bits, |
| 24672 | }; |
| 24673 | const tag_ty = Type.initPayload(&buffer.base); |
| 24674 | return intInRange(sema, block, src, tag_ty, int, fields_len); |
| 24675 | }, |
| 24676 | .atomic_order, |
| 24677 | .atomic_rmw_op, |
| 24678 | .calling_convention, |
| 24679 | .address_space, |
| 24680 | .float_mode, |
| 24681 | .reduce_op, |
| 24682 | .call_options, |
| 24683 | .prefetch_options, |
| 24684 | .export_options, |
| 24685 | .extern_options, |
| 24686 | => unreachable, |
| 24687 | |
| 24688 | else => unreachable, |
| 24689 | } |
| 24690 | } |
| 24691 | |
| 24692 | fn intAddWithOverflow( |
| 24693 | sema: *Sema, |
| 24694 | block: *Block, |
| 24695 | src: LazySrcLoc, |
| 24696 | lhs: Value, |
| 24697 | rhs: Value, |
| 24698 | ty: Type, |
| 24699 | ) !Value.OverflowArithmeticResult { |
| 24700 | if (ty.zigTypeTag() == .Vector) { |
| 24701 | const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24702 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24703 | for (result_data) |*scalar, i| { |
| 24704 | const of_math_result = try sema.intAddWithOverflowScalar(block, src, lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType()); |
| 24705 | overflowed_data[i] = of_math_result.overflowed; |
| 24706 | scalar.* = of_math_result.wrapped_result; |
| 24707 | } |
| 24708 | return Value.OverflowArithmeticResult{ |
| 24709 | .overflowed = try Value.Tag.aggregate.create(sema.arena, overflowed_data), |
| 24710 | .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data), |
| 24711 | }; |
| 24712 | } |
| 24713 | return sema.intAddWithOverflowScalar(block, src, lhs, rhs, ty); |
| 24714 | } |
| 24715 | |
| 24716 | fn intAddWithOverflowScalar( |
| 24717 | sema: *Sema, |
| 24718 | block: *Block, |
| 24719 | src: LazySrcLoc, |
| 24720 | lhs: Value, |
| 24721 | rhs: Value, |
| 24722 | ty: Type, |
| 24723 | ) !Value.OverflowArithmeticResult { |
| 24724 | const target = sema.mod.getTarget(); |
| 24725 | const info = ty.intInfo(target); |
| 24726 | |
| 24727 | var lhs_space: Value.BigIntSpace = undefined; |
| 24728 | var rhs_space: Value.BigIntSpace = undefined; |
| 24729 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, src)); |
| 24730 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, src)); |
| 24731 | const limbs = try sema.arena.alloc( |
| 24732 | std.math.big.Limb, |
| 24733 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 24734 | ); |
| 24735 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 24736 | const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 24737 | const result = try Value.fromBigInt(sema.arena, result_bigint.toConst()); |
| 24738 | return Value.OverflowArithmeticResult{ |
| 24739 | .overflowed = Value.makeBool(overflowed), |
| 24740 | .wrapped_result = result, |
| 24741 | }; |
| 24742 | } |
| 24743 | |
| 24744 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 24745 | /// Vector results will be reduced with AND. |
| 24746 | fn compare( |
| 24747 | sema: *Sema, |
| 24748 | block: *Block, |
| 24749 | src: LazySrcLoc, |
| 24750 | lhs: Value, |
| 24751 | op: std.math.CompareOperator, |
| 24752 | rhs: Value, |
| 24753 | ty: Type, |
| 24754 | ) CompileError!bool { |
| 24755 | if (ty.zigTypeTag() == .Vector) { |
| 24756 | var i: usize = 0; |
| 24757 | while (i < ty.vectorLen()) : (i += 1) { |
| 24758 | if (!(try sema.compareScalar(block, src, lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType()))) { |
| 24759 | return false; |
| 24760 | } |
| 24761 | } |
| 24762 | return true; |
| 24763 | } |
| 24764 | return sema.compareScalar(block, src, lhs, op, rhs, ty); |
| 24765 | } |
| 24766 | |
| 24767 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 24768 | fn compareScalar( |
| 24769 | sema: *Sema, |
| 24770 | block: *Block, |
| 24771 | src: LazySrcLoc, |
| 24772 | lhs: Value, |
| 24773 | op: std.math.CompareOperator, |
| 24774 | rhs: Value, |
| 24775 | ty: Type, |
| 24776 | ) CompileError!bool { |
| 24777 | switch (op) { |
| 24778 | .eq => return sema.valuesEqual(block, src, lhs, rhs, ty), |
| 24779 | .neq => return !(try sema.valuesEqual(block, src, lhs, rhs, ty)), |
| 24780 | else => return Value.compareHeteroAdvanced(lhs, op, rhs, sema.mod.getTarget(), sema.kit(block, src)), |
| 24781 | } |
| 24782 | } |
| 24783 | |
| 24784 | fn valuesEqual( |
| 24785 | sema: *Sema, |
| 24786 | block: *Block, |
| 24787 | src: LazySrcLoc, |
| 24788 | lhs: Value, |
| 24789 | rhs: Value, |
| 24790 | ty: Type, |
| 24791 | ) CompileError!bool { |
| 24792 | return Value.eqlAdvanced(lhs, rhs, ty, sema.mod, sema.kit(block, src)); |
| 24793 | } |
| 24794 | |
| 24795 | /// Asserts the values are comparable vectors of type `ty`. |
| 24796 | pub fn compareVector( |
| 24797 | sema: *Sema, |
| 24798 | block: *Block, |
| 24799 | src: LazySrcLoc, |
| 24800 | lhs: Value, |
| 24801 | op: std.math.CompareOperator, |
| 24802 | rhs: Value, |
| 24803 | ty: Type, |
| 24804 | ) !Value { |
| 24805 | assert(ty.zigTypeTag() == .Vector); |
| 24806 | const result_data = try sema.arena.alloc(Value, ty.vectorLen()); |
| 24807 | for (result_data) |*scalar, i| { |
| 24808 | const res_bool = try sema.compareScalar(block, src, lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType()); |
| 24809 | scalar.* = Value.makeBool(res_bool); |
| 24810 | } |
| 24811 | return Value.Tag.aggregate.create(sema.arena, result_data); |
| 24812 | } |