authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-20 18:35:19-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-20 18:35:19-04:00
log1a92264b3d3f3e14f9a3b724fccefb5f5a38346f
treebf2447d9fed7334cbe1a909398f53396879a8609
parent704d38ba4981d46ac1d4687d8f6dcce72bf4067c
parentfcd4efd8ecda01fe06735ed8b7e2cd2aa93daa19
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11671 from ziglang/stage2-behavior

stage2 bug fixes aimed towards more behavior tests passing

10 files changed, 1162 insertions(+), 847 deletions(-)

src/AstGen.zig+14-1
......@@ -71,6 +71,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
7171 Zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
7272 i32 => @bitCast(u32, @field(extra, field.name)),
7373 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
74 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),
7475 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
7576 Zir.Inst.ExtendedFunc.Bits => @bitCast(u32, @field(extra, field.name)),
7677 else => @compileError("bad field type"),
......@@ -2213,6 +2214,14 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22132214 slot.* = @bitCast(u32, flags);
22142215 break :b true;
22152216 },
2217 .builtin_call => {
2218 const extra_index = gz.astgen.instructions.items(.data)[inst].pl_node.payload_index;
2219 const slot = &gz.astgen.extra.items[extra_index];
2220 var flags = @bitCast(Zir.Inst.BuiltinCall.Flags, slot.*);
2221 flags.ensure_result_used = true;
2222 slot.* = @bitCast(u32, flags);
2223 break :b true;
2224 },
22162225
22172226 // ZIR instructions that might be a type other than `noreturn` or `void`.
22182227 .add,
......@@ -2412,7 +2421,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
24122421 .atomic_load,
24132422 .atomic_rmw,
24142423 .mul_add,
2415 .builtin_call,
24162424 .field_parent_ptr,
24172425 .maximum,
24182426 .minimum,
......@@ -7502,6 +7510,11 @@ fn builtinCall(
75027510 .options = options,
75037511 .callee = callee,
75047512 .args = args,
7513 .flags = .{
7514 .is_nosuspend = gz.nosuspend_node != 0,
7515 .is_comptime = gz.force_comptime,
7516 .ensure_result_used = false,
7517 },
75057518 });
75067519 return rvalue(gz, rl, result, node);
75077520 },
src/Sema.zig+864-138
......@@ -2228,7 +2228,6 @@ fn zirEnumDecl(
22282228 enum_obj.tag_ty_inferred = true;
22292229 }
22302230 }
2231 const target = mod.getTarget();
22322231
22332232 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
22342233 const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| {
......@@ -2291,7 +2290,7 @@ fn zirEnumDecl(
22912290 });
22922291 } else if (any_values) {
22932292 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)
22952294 else
22962295 Value.zero;
22972296 last_tag_val = tag_val;
......@@ -6054,7 +6053,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
60546053 if (int_val.isUndef()) {
60556054 return sema.failWithUseOfUndef(block, operand_src);
60566055 }
6057 if (!dest_ty.enumHasInt(int_val, sema.mod)) {
6056 if (!(try sema.enumHasInt(block, src, dest_ty, int_val))) {
60586057 const msg = msg: {
60596058 const msg = try sema.errMsg(
60606059 block,
......@@ -7082,7 +7081,7 @@ fn intCast(
70827081 // range to account for negative values.
70837082 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
70847083 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);
70867085 } else dest_max_val;
70877086 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
70887087
......@@ -7236,8 +7235,8 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
72367235 ),
72377236 }
72387237
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));
72417240 }
72427241 if (dest_is_comptime_float) {
72437242 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
82038202 // Validation above ensured these will succeed.
82048203 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable;
82058204 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)))
82088207 {
82098208 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
82108209 }
......@@ -8878,7 +8877,7 @@ fn zirShl(
88788877 if (rhs_val.isUndef()) {
88798878 return sema.addConstUndef(sema.typeOf(lhs));
88808879 }
8881 if (rhs_val.compareWithZero(.eq)) {
8880 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
88828881 return lhs;
88838882 }
88848883 }
......@@ -8895,7 +8894,7 @@ fn zirShl(
88958894 }
88968895 const int_info = scalar_ty.intInfo(target);
88978896 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)) {
88998898 break :val shifted;
89008899 }
89018900 return sema.addConstUndef(lhs_ty);
......@@ -8999,13 +8998,13 @@ fn zirShr(
89998998 return sema.addConstUndef(lhs_ty);
90008999 }
90019000 // 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))) {
90039002 return sema.addConstant(lhs_ty, lhs_val);
90049003 }
90059004 if (air_tag == .shr_exact) {
90069005 // Detect if any ones would be shifted out.
90079006 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)))) {
90099008 return sema.addConstUndef(lhs_ty);
90109009 }
90119010 }
......@@ -9015,7 +9014,7 @@ fn zirShr(
90159014 // Even if lhs is not comptime known, we can still deduce certain things based
90169015 // on rhs.
90179016 // 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))) {
90199018 return lhs;
90209019 }
90219020 break :rs lhs_src;
......@@ -9578,12 +9577,12 @@ fn zirOverflowArithmetic(
95789577 // to the result, even if it is undefined..
95799578 // Otherwise, if either of the argument is undefined, undefined is returned.
95809579 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)))) {
95829581 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
95839582 }
95849583 }
95859584 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)))) {
95879586 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
95889587 }
95899588 }
......@@ -9593,7 +9592,7 @@ fn zirOverflowArithmetic(
95939592 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
95949593 }
95959594
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);
95979596 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
95989597 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
95999598 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
......@@ -9606,14 +9605,14 @@ fn zirOverflowArithmetic(
96069605 if (maybe_rhs_val) |rhs_val| {
96079606 if (rhs_val.isUndef()) {
96089607 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))) {
96109609 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
96119610 } else if (maybe_lhs_val) |lhs_val| {
96129611 if (lhs_val.isUndef()) {
96139612 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
96149613 }
96159614
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);
96179616 const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
96189617 const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
96199618 break :result .{ .overflowed = overflowed, .wrapped = wrapped };
......@@ -9626,9 +9625,9 @@ fn zirOverflowArithmetic(
96269625 // Otherwise, if either of the arguments is undefined, both results are undefined.
96279626 if (maybe_lhs_val) |lhs_val| {
96289627 if (!lhs_val.isUndef()) {
9629 if (lhs_val.compareWithZero(.eq)) {
9628 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
96309629 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)) {
96329631 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
96339632 }
96349633 }
......@@ -9636,9 +9635,9 @@ fn zirOverflowArithmetic(
96369635
96379636 if (maybe_rhs_val) |rhs_val| {
96389637 if (!rhs_val.isUndef()) {
9639 if (rhs_val.compareWithZero(.eq)) {
9638 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
96409639 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)) {
96429641 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
96439642 }
96449643 }
......@@ -9662,12 +9661,12 @@ fn zirOverflowArithmetic(
96629661 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
96639662 // Oterhwise if either of the arguments is undefined, both results are undefined.
96649663 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)))) {
96669665 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
96679666 }
96689667 }
96699668 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)))) {
96719670 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
96729671 }
96739672 }
......@@ -9815,7 +9814,7 @@ fn analyzeArithmetic(
98159814 // overflow (max_int), causing illegal behavior.
98169815 // For floats: either operand being undef makes the result undef.
98179816 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)))) {
98199818 return casted_rhs;
98209819 }
98219820 }
......@@ -9827,7 +9826,7 @@ fn analyzeArithmetic(
98279826 return sema.addConstUndef(resolved_type);
98289827 }
98299828 }
9830 if (rhs_val.compareWithZero(.eq)) {
9829 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
98319830 return casted_lhs;
98329831 }
98339832 }
......@@ -9841,15 +9840,15 @@ fn analyzeArithmetic(
98419840 }
98429841 if (maybe_rhs_val) |rhs_val| {
98439842 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))) {
98469845 return sema.failWithIntegerOverflow(block, src, resolved_type, sum);
98479846 }
98489847 return sema.addConstant(resolved_type, sum);
98499848 } else {
98509849 return sema.addConstant(
98519850 resolved_type,
9852 try lhs_val.floatAdd(rhs_val, resolved_type, sema.arena, target),
9851 try sema.floatAdd(lhs_val, rhs_val, resolved_type),
98539852 );
98549853 }
98559854 } else break :rs .{ .src = rhs_src, .air_tag = .add };
......@@ -9860,7 +9859,7 @@ fn analyzeArithmetic(
98609859 // If either of the operands are zero, the other operand is returned.
98619860 // If either of the operands are undefined, the result is undefined.
98629861 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)))) {
98649863 return casted_rhs;
98659864 }
98669865 }
......@@ -9868,13 +9867,13 @@ fn analyzeArithmetic(
98689867 if (rhs_val.isUndef()) {
98699868 return sema.addConstUndef(resolved_type);
98709869 }
9871 if (rhs_val.compareWithZero(.eq)) {
9870 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
98729871 return casted_lhs;
98739872 }
98749873 if (maybe_lhs_val) |lhs_val| {
98759874 return sema.addConstant(
98769875 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),
98789877 );
98799878 } else break :rs .{ .src = lhs_src, .air_tag = .addwrap };
98809879 } else break :rs .{ .src = rhs_src, .air_tag = .addwrap };
......@@ -9884,7 +9883,7 @@ fn analyzeArithmetic(
98849883 // If either of the operands are zero, then the other operand is returned.
98859884 // If either of the operands are undefined, the result is undefined.
98869885 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)))) {
98889887 return casted_rhs;
98899888 }
98909889 }
......@@ -9892,12 +9891,12 @@ fn analyzeArithmetic(
98929891 if (rhs_val.isUndef()) {
98939892 return sema.addConstUndef(resolved_type);
98949893 }
9895 if (rhs_val.compareWithZero(.eq)) {
9894 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
98969895 return casted_lhs;
98979896 }
98989897 if (maybe_lhs_val) |lhs_val| {
98999898 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)
99019900 else
99029901 try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, target);
99039902
......@@ -9921,7 +9920,7 @@ fn analyzeArithmetic(
99219920 return sema.addConstUndef(resolved_type);
99229921 }
99239922 }
9924 if (rhs_val.compareWithZero(.eq)) {
9923 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
99259924 return casted_lhs;
99269925 }
99279926 }
......@@ -9935,15 +9934,15 @@ fn analyzeArithmetic(
99359934 }
99369935 if (maybe_rhs_val) |rhs_val| {
99379936 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))) {
99409939 return sema.failWithIntegerOverflow(block, src, resolved_type, diff);
99419940 }
99429941 return sema.addConstant(resolved_type, diff);
99439942 } else {
99449943 return sema.addConstant(
99459944 resolved_type,
9946 try lhs_val.floatSub(rhs_val, resolved_type, sema.arena, target),
9945 try sema.floatSub(lhs_val, rhs_val, resolved_type),
99479946 );
99489947 }
99499948 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
......@@ -9957,7 +9956,7 @@ fn analyzeArithmetic(
99579956 if (rhs_val.isUndef()) {
99589957 return sema.addConstUndef(resolved_type);
99599958 }
9960 if (rhs_val.compareWithZero(.eq)) {
9959 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
99619960 return casted_lhs;
99629961 }
99639962 }
......@@ -9968,7 +9967,7 @@ fn analyzeArithmetic(
99689967 if (maybe_rhs_val) |rhs_val| {
99699968 return sema.addConstant(
99709969 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),
99729971 );
99739972 } else break :rs .{ .src = rhs_src, .air_tag = .subwrap };
99749973 } else break :rs .{ .src = lhs_src, .air_tag = .subwrap };
......@@ -9981,7 +9980,7 @@ fn analyzeArithmetic(
99819980 if (rhs_val.isUndef()) {
99829981 return sema.addConstUndef(resolved_type);
99839982 }
9984 if (rhs_val.compareWithZero(.eq)) {
9983 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
99859984 return casted_lhs;
99869985 }
99879986 }
......@@ -9991,7 +9990,7 @@ fn analyzeArithmetic(
99919990 }
99929991 if (maybe_rhs_val) |rhs_val| {
99939992 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)
99959994 else
99969995 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, target);
99979996
......@@ -10032,7 +10031,7 @@ fn analyzeArithmetic(
1003210031 .Int, .ComptimeInt, .ComptimeFloat => {
1003310032 if (maybe_lhs_val) |lhs_val| {
1003410033 if (!lhs_val.isUndef()) {
10035 if (lhs_val.compareWithZero(.eq)) {
10034 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1003610035 return sema.addConstant(resolved_type, Value.zero);
1003710036 }
1003810037 }
......@@ -10041,7 +10040,7 @@ fn analyzeArithmetic(
1004110040 if (rhs_val.isUndef()) {
1004210041 return sema.failWithUseOfUndef(block, rhs_src);
1004310042 }
10044 if (rhs_val.compareWithZero(.eq)) {
10043 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1004510044 return sema.failWithDivideByZero(block, rhs_src);
1004610045 }
1004710046 }
......@@ -10053,7 +10052,7 @@ fn analyzeArithmetic(
1005310052 if (lhs_val.isUndef()) {
1005410053 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1005510054 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)) {
1005710056 return sema.addConstUndef(resolved_type);
1005810057 }
1005910058 }
......@@ -10111,7 +10110,7 @@ fn analyzeArithmetic(
1011110110 // If the lhs is undefined, result is undefined.
1011210111 if (maybe_lhs_val) |lhs_val| {
1011310112 if (!lhs_val.isUndef()) {
10114 if (lhs_val.compareWithZero(.eq)) {
10113 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1011510114 return sema.addConstant(resolved_type, Value.zero);
1011610115 }
1011710116 }
......@@ -10120,7 +10119,7 @@ fn analyzeArithmetic(
1012010119 if (rhs_val.isUndef()) {
1012110120 return sema.failWithUseOfUndef(block, rhs_src);
1012210121 }
10123 if (rhs_val.compareWithZero(.eq)) {
10122 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1012410123 return sema.failWithDivideByZero(block, rhs_src);
1012510124 }
1012610125 }
......@@ -10128,7 +10127,7 @@ fn analyzeArithmetic(
1012810127 if (lhs_val.isUndef()) {
1012910128 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1013010129 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)) {
1013210131 return sema.addConstUndef(resolved_type);
1013310132 }
1013410133 }
......@@ -10174,7 +10173,7 @@ fn analyzeArithmetic(
1017410173 // If the lhs is undefined, result is undefined.
1017510174 if (maybe_lhs_val) |lhs_val| {
1017610175 if (!lhs_val.isUndef()) {
10177 if (lhs_val.compareWithZero(.eq)) {
10176 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1017810177 return sema.addConstant(resolved_type, Value.zero);
1017910178 }
1018010179 }
......@@ -10183,7 +10182,7 @@ fn analyzeArithmetic(
1018310182 if (rhs_val.isUndef()) {
1018410183 return sema.failWithUseOfUndef(block, rhs_src);
1018510184 }
10186 if (rhs_val.compareWithZero(.eq)) {
10185 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1018710186 return sema.failWithDivideByZero(block, rhs_src);
1018810187 }
1018910188 }
......@@ -10191,7 +10190,7 @@ fn analyzeArithmetic(
1019110190 if (lhs_val.isUndef()) {
1019210191 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1019310192 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)) {
1019510194 return sema.addConstUndef(resolved_type);
1019610195 }
1019710196 }
......@@ -10236,7 +10235,7 @@ fn analyzeArithmetic(
1023610235 if (lhs_val.isUndef()) {
1023710236 return sema.failWithUseOfUndef(block, rhs_src);
1023810237 } else {
10239 if (lhs_val.compareWithZero(.eq)) {
10238 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1024010239 return sema.addConstant(resolved_type, Value.zero);
1024110240 }
1024210241 }
......@@ -10245,7 +10244,7 @@ fn analyzeArithmetic(
1024510244 if (rhs_val.isUndef()) {
1024610245 return sema.failWithUseOfUndef(block, rhs_src);
1024710246 }
10248 if (rhs_val.compareWithZero(.eq)) {
10247 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1024910248 return sema.failWithDivideByZero(block, rhs_src);
1025010249 }
1025110250 }
......@@ -10278,10 +10277,10 @@ fn analyzeArithmetic(
1027810277 // For floats: either operand being undef makes the result undef.
1027910278 if (maybe_lhs_val) |lhs_val| {
1028010279 if (!lhs_val.isUndef()) {
10281 if (lhs_val.compareWithZero(.eq)) {
10280 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1028210281 return sema.addConstant(resolved_type, Value.zero);
1028310282 }
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)) {
1028510284 return casted_rhs;
1028610285 }
1028710286 }
......@@ -10294,10 +10293,10 @@ fn analyzeArithmetic(
1029410293 return sema.addConstUndef(resolved_type);
1029510294 }
1029610295 }
10297 if (rhs_val.compareWithZero(.eq)) {
10296 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1029810297 return sema.addConstant(resolved_type, Value.zero);
1029910298 }
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)) {
1030110300 return casted_lhs;
1030210301 }
1030310302 if (maybe_lhs_val) |lhs_val| {
......@@ -10310,7 +10309,7 @@ fn analyzeArithmetic(
1031010309 }
1031110310 if (is_int) {
1031210311 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))) {
1031410313 return sema.failWithIntegerOverflow(block, src, resolved_type, product);
1031510314 }
1031610315 return sema.addConstant(resolved_type, product);
......@@ -10330,10 +10329,10 @@ fn analyzeArithmetic(
1033010329 // If either of the operands are undefined, result is undefined.
1033110330 if (maybe_lhs_val) |lhs_val| {
1033210331 if (!lhs_val.isUndef()) {
10333 if (lhs_val.compareWithZero(.eq)) {
10332 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1033410333 return sema.addConstant(resolved_type, Value.zero);
1033510334 }
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)) {
1033710336 return casted_rhs;
1033810337 }
1033910338 }
......@@ -10342,10 +10341,10 @@ fn analyzeArithmetic(
1034210341 if (rhs_val.isUndef()) {
1034310342 return sema.addConstUndef(resolved_type);
1034410343 }
10345 if (rhs_val.compareWithZero(.eq)) {
10344 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1034610345 return sema.addConstant(resolved_type, Value.zero);
1034710346 }
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)) {
1034910348 return casted_lhs;
1035010349 }
1035110350 if (maybe_lhs_val) |lhs_val| {
......@@ -10366,10 +10365,10 @@ fn analyzeArithmetic(
1036610365 // If either of the operands are undefined, result is undefined.
1036710366 if (maybe_lhs_val) |lhs_val| {
1036810367 if (!lhs_val.isUndef()) {
10369 if (lhs_val.compareWithZero(.eq)) {
10368 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1037010369 return sema.addConstant(resolved_type, Value.zero);
1037110370 }
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)) {
1037310372 return casted_rhs;
1037410373 }
1037510374 }
......@@ -10378,10 +10377,10 @@ fn analyzeArithmetic(
1037810377 if (rhs_val.isUndef()) {
1037910378 return sema.addConstUndef(resolved_type);
1038010379 }
10381 if (rhs_val.compareWithZero(.eq)) {
10380 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1038210381 return sema.addConstant(resolved_type, Value.zero);
1038310382 }
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)) {
1038510384 return casted_lhs;
1038610385 }
1038710386 if (maybe_lhs_val) |lhs_val| {
......@@ -10417,7 +10416,7 @@ fn analyzeArithmetic(
1041710416 if (lhs_val.isUndef()) {
1041810417 return sema.failWithUseOfUndef(block, lhs_src);
1041910418 }
10420 if (lhs_val.compareWithZero(.eq)) {
10419 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1042110420 return sema.addConstant(resolved_type, Value.zero);
1042210421 }
1042310422 } else if (lhs_scalar_ty.isSignedInt()) {
......@@ -10427,23 +10426,23 @@ fn analyzeArithmetic(
1042710426 if (rhs_val.isUndef()) {
1042810427 return sema.failWithUseOfUndef(block, rhs_src);
1042910428 }
10430 if (rhs_val.compareWithZero(.eq)) {
10429 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1043110430 return sema.failWithDivideByZero(block, rhs_src);
1043210431 }
1043310432 if (maybe_lhs_val) |lhs_val| {
1043410433 const rem_result = try lhs_val.intRem(rhs_val, resolved_type, sema.arena, target);
1043510434 // If this answer could possibly be different by doing `intMod`,
1043610435 // 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))))
1043910438 {
10440 const bad_src = if (lhs_val.compareWithZero(.lt))
10439 const bad_src = if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))
1044110440 lhs_src
1044210441 else
1044310442 rhs_src;
1044410443 return sema.failWithModRemNegative(block, bad_src, lhs_ty, rhs_ty);
1044510444 }
10446 if (lhs_val.compareWithZero(.lt)) {
10445 if (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) {
1044710446 // Negative
1044810447 return sema.addConstant(resolved_type, Value.zero);
1044910448 }
......@@ -10461,14 +10460,14 @@ fn analyzeArithmetic(
1046110460 if (rhs_val.isUndef()) {
1046210461 return sema.failWithUseOfUndef(block, rhs_src);
1046310462 }
10464 if (rhs_val.compareWithZero(.eq)) {
10463 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1046510464 return sema.failWithDivideByZero(block, rhs_src);
1046610465 }
10467 if (rhs_val.compareWithZero(.lt)) {
10466 if (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) {
1046810467 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
1046910468 }
1047010469 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)))) {
1047210471 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
1047310472 }
1047410473 return sema.addConstant(
......@@ -10504,7 +10503,7 @@ fn analyzeArithmetic(
1050410503 if (rhs_val.isUndef()) {
1050510504 return sema.failWithUseOfUndef(block, rhs_src);
1050610505 }
10507 if (rhs_val.compareWithZero(.eq)) {
10506 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1050810507 return sema.failWithDivideByZero(block, rhs_src);
1050910508 }
1051010509 if (maybe_lhs_val) |lhs_val| {
......@@ -10523,7 +10522,7 @@ fn analyzeArithmetic(
1052310522 if (rhs_val.isUndef()) {
1052410523 return sema.failWithUseOfUndef(block, rhs_src);
1052510524 }
10526 if (rhs_val.compareWithZero(.eq)) {
10525 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1052710526 return sema.failWithDivideByZero(block, rhs_src);
1052810527 }
1052910528 }
......@@ -10561,7 +10560,7 @@ fn analyzeArithmetic(
1056110560 if (rhs_val.isUndef()) {
1056210561 return sema.failWithUseOfUndef(block, rhs_src);
1056310562 }
10564 if (rhs_val.compareWithZero(.eq)) {
10563 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1056510564 return sema.failWithDivideByZero(block, rhs_src);
1056610565 }
1056710566 if (maybe_lhs_val) |lhs_val| {
......@@ -10580,7 +10579,7 @@ fn analyzeArithmetic(
1058010579 if (rhs_val.isUndef()) {
1058110580 return sema.failWithUseOfUndef(block, rhs_src);
1058210581 }
10583 if (rhs_val.compareWithZero(.eq)) {
10582 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
1058410583 return sema.failWithDivideByZero(block, rhs_src);
1058510584 }
1058610585 }
......@@ -11095,11 +11094,11 @@ fn cmpSelf(
1109511094
1109611095 if (resolved_type.zigTypeTag() == .Vector) {
1109711096 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);
1109911098 return sema.addConstant(result_ty, cmp_val);
1110011099 }
1110111100
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)) {
1110311102 return Air.Inst.Ref.bool_true;
1110411103 } else {
1110511104 return Air.Inst.Ref.bool_false;
......@@ -11157,24 +11156,22 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1115711156 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1115811157 const src = inst_data.src();
1115911158 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()) {
1116411161 .Fn => unreachable,
1116511162 .NoReturn,
1116611163 .Undefined,
1116711164 .Null,
1116811165 .BoundFn,
1116911166 .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)}),
1117111168
1117211169 .Type,
1117311170 .EnumLiteral,
1117411171 .ComptimeFloat,
1117511172 .ComptimeInt,
1117611173 .Void,
11177 => 0,
11174 => return sema.addIntUnsigned(Type.comptime_int, 0),
1117811175
1117911176 .Bool,
1118011177 .Int,
......@@ -11190,9 +11187,14 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1119011187 .Vector,
1119111188 .Frame,
1119211189 .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);
1119611198}
1119711199
1119811200fn 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
1120211204 const operand_ty = try sema.resolveTypeFields(block, operand_src, unresolved_operand_ty);
1120311205 const target = sema.mod.getTarget();
1120411206 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);
1120611208}
1120711209
1120811210fn zirThis(
......@@ -13516,10 +13518,11 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1351613518 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1351713519 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
1351813520 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);
1352313526}
1352413527
1352513528fn 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!
1436214365 try sema.checkFloatType(block, operand_src, operand_ty);
1436314366
1436414367 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);
1437514369 return sema.addConstant(dest_ty, result_val);
1437614370 }
1437714371
......@@ -15563,7 +15557,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1556315557 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, target),
1556415558 .Min => accum = accum.numberMin(elem_val, target),
1556515559 .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),
1556715561 .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, target),
1556815562 }
1556915563 }
......@@ -15958,14 +15952,14 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1595815952 const new_val = switch (op) {
1595915953 // zig fmt: off
1596015954 .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),
1596915963 // zig fmt: on
1597015964 };
1597115965 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
1609716091 const args_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
1609816092 const call_src = inst_data.src();
1609916093
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);
1610416098
16105 const modifier: std.builtin.CallOptions.Modifier = modifier: {
16099 const wanted_modifier: std.builtin.CallOptions.Modifier = modifier: {
1610616100 const call_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions");
1610716101 const coerced_options = try sema.coerce(block, call_options_ty, options, options_src);
1610816102
......@@ -16118,6 +16112,41 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1611816112 break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier);
1611916113 };
1612016114
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
1612116150 const args_ty = sema.typeOf(args);
1612216151 if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) {
1612316152 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
1614116170 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
1614216171 }
1614316172 }
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);
1614616175}
1614716176
1614816177fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -18855,18 +18884,13 @@ fn coerce(
1885518884 .{ val.fmtValue(inst_ty, sema.mod), dest_ty.fmt(sema.mod) },
1885618885 );
1885718886 }
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);
1886418888 return try sema.addConstant(dest_ty, result_val);
1886518889 },
1886618890 .Int, .ComptimeInt => {
1886718891 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
1886818892 // comptime known integer to other number
18869 if (!val.intFitsInType(dest_ty, target)) {
18893 if (!(try sema.intFitsInType(block, inst_src, val, dest_ty))) {
1887018894 return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });
1887118895 }
1887218896 return try sema.addConstant(dest_ty, val);
......@@ -21058,7 +21082,7 @@ fn analyzeSlice(
2105821082 sema.arena,
2105921083 array_ty.arrayLenIncludingSentinel(),
2106021084 );
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)) {
2106221086 const sentinel_label: []const u8 = if (array_ty.sentinel() != null)
2106321087 " +1 (sentinel)"
2106421088 else
......@@ -21098,7 +21122,7 @@ fn analyzeSlice(
2109821122 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),
2109921123 };
2110021124 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)) {
2110221126 const sentinel_label: []const u8 = if (has_sentinel)
2110321127 " +1 (sentinel)"
2110421128 else
......@@ -21156,7 +21180,7 @@ fn analyzeSlice(
2115621180 // requirement: start <= end
2115721181 if (try sema.resolveDefinedValue(block, src, end)) |end_val| {
2115821182 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)) {
2116021184 return sema.fail(
2116121185 block,
2116221186 start_src,
......@@ -21364,11 +21388,11 @@ fn cmpNumeric(
2136421388 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
2136521389 // add/subtract 1.
2136621390 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)))
2136821392 else
2136921393 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());
2137021394 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)))
2137221396 else
2137321397 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());
2137421398 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
......@@ -21506,7 +21530,7 @@ fn cmpVector(
2150621530 if (lhs_val.isUndef() or rhs_val.isUndef()) {
2150721531 return sema.addConstUndef(result_ty);
2150821532 }
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);
2151021534 return sema.addConstant(result_ty, cmp_val);
2151121535 } else {
2151221536 break :src rhs_src;
......@@ -22869,8 +22893,6 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
2286922893 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
2287022894 }
2287122895
22872 const target = sema.mod.getTarget();
22873
2287422896 const bits_per_field = 4;
2287522897 const fields_per_u32 = 32 / bits_per_field;
2287622898 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
2293422956 });
2293522957 } else {
2293622958 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)
2293822960 else
2293922961 Value.zero;
2294022962 last_tag_val = val;
......@@ -24084,3 +24106,707 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {
2408424106 const inst_ref = try sema.addType(ty);
2408524107 try sema.types_to_resolve.append(sema.gpa, inst_ref);
2408624108}
24109
24110fn 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
24121fn 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.
24139fn 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.
24158fn 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
24180fn 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
24198fn 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.
24216fn 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.
24235fn 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
24257fn 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
24273fn 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
24310fn 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
24326fn 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
24363fn 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
24387fn 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
24415fn 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
24434fn 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.
24486fn 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
24613fn 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.
24632fn 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
24692fn 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
24716fn 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.
24746fn 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`.
24768fn 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
24784fn 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`.
24796pub 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}
src/TypedValue.zig+5
......@@ -232,6 +232,11 @@ pub fn print(
232232 const x = sub_ty.abiAlignment(target);
233233 return writer.print("{d}", .{x});
234234 },
235 .lazy_size => {
236 const sub_ty = val.castTag(.lazy_size).?.data;
237 const x = sub_ty.abiSize(target);
238 return writer.print("{d}", .{x});
239 },
235240 .function => return writer.print("(function '{s}')", .{
236241 mod.declPtr(val.castTag(.function).?.data.owner_decl).name,
237242 }),
src/Zir.zig+22-4
......@@ -72,6 +72,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
7272 Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
7373 i32 => @bitCast(i32, code.extra[i]),
7474 Inst.Call.Flags => @bitCast(Inst.Call.Flags, code.extra[i]),
75 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),
7576 Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),
7677 Inst.ExtendedFunc.Bits => @bitCast(Inst.ExtendedFunc.Bits, code.extra[i]),
7778 else => @compileError("bad field type"),
......@@ -280,8 +281,13 @@ pub const Inst = struct {
280281 /// Uses the `break` union field.
281282 break_inline,
282283 /// Function call.
283 /// Uses `pl_node`. AST node is the function call. Payload is `Call`.
284 /// Uses the `pl_node` union field with payload `Call`.
285 /// AST node is the function call.
284286 call,
287 /// Implements the `@call` builtin.
288 /// Uses the `pl_node` union field with payload `BuiltinCall`.
289 /// AST node is the builtin call.
290 builtin_call,
285291 /// `<`
286292 /// Uses the `pl_node` union field. Payload is `Bin`.
287293 cmp_lt,
......@@ -916,9 +922,6 @@ pub const Inst = struct {
916922 /// The addend communicates the type of the builtin.
917923 /// The mulends need to be coerced to the same type.
918924 mul_add,
919 /// Implements the `@call` builtin.
920 /// Uses the `pl_node` union field with payload `BuiltinCall`.
921 builtin_call,
922925 /// Implements the `@fieldParentPtr` builtin.
923926 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
924927 field_parent_ptr,
......@@ -2733,9 +2736,24 @@ pub const Inst = struct {
27332736 };
27342737
27352738 pub const BuiltinCall = struct {
2739 // Note: Flags *must* come first so that unusedResultExpr
2740 // can find it when it goes to modify them.
2741 flags: Flags,
27362742 options: Ref,
27372743 callee: Ref,
27382744 args: Ref,
2745
2746 pub const Flags = packed struct {
2747 is_nosuspend: bool,
2748 is_comptime: bool,
2749 ensure_result_used: bool,
2750 _: u29 = undefined,
2751
2752 comptime {
2753 if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32)
2754 @compileError("Layout of BuiltinCall.Flags needs to be updated!");
2755 }
2756 };
27392757 };
27402758
27412759 /// This data is stored inside extra, with two sets of trailing `Ref`:
src/print_zir.zig+7-2
......@@ -365,7 +365,7 @@ const Writer = struct {
365365 .@"export" => try self.writePlNodeExport(stream, inst),
366366 .export_value => try self.writePlNodeExportValue(stream, inst),
367367
368 .call => try self.writePlNodeCall(stream, inst),
368 .call => try self.writeCall(stream, inst),
369369
370370 .block,
371371 .block_inline,
......@@ -793,6 +793,11 @@ const Writer = struct {
793793 fn writeBuiltinCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
794794 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
795795 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
796
797 try self.writeFlag(stream, "nodiscard ", extra.flags.ensure_result_used);
798 try self.writeFlag(stream, "nosuspend ", extra.flags.is_nosuspend);
799 try self.writeFlag(stream, "comptime ", extra.flags.is_comptime);
800
796801 try self.writeInstRef(stream, extra.options);
797802 try stream.writeAll(", ");
798803 try self.writeInstRef(stream, extra.callee);
......@@ -1144,7 +1149,7 @@ const Writer = struct {
11441149 try self.writeSrc(stream, src);
11451150 }
11461151
1147 fn writePlNodeCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1152 fn writeCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
11481153 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
11491154 const extra = self.code.extraData(Zir.Inst.Call, inst_data.payload_index);
11501155 const args = self.code.refSlice(extra.end, extra.data.flags.args_len);
src/type.zig+154-137
......@@ -2760,7 +2760,7 @@ pub const Type = extern union {
27602760 .sema_kit => |sk| sk,
27612761 else => null,
27622762 };
2763 return switch (ty.tag()) {
2763 switch (ty.tag()) {
27642764 .u1,
27652765 .u8,
27662766 .i8,
......@@ -3028,7 +3028,7 @@ pub const Type = extern union {
30283028 => unreachable,
30293029
30303030 .generic_poison => unreachable,
3031 };
3031 }
30323032 }
30333033
30343034 pub fn abiAlignmentAdvancedUnion(
......@@ -3076,10 +3076,37 @@ pub const Type = extern union {
30763076 return AbiAlignmentAdvanced{ .scalar = max_align };
30773077 }
30783078
3079 /// May capture a reference to `ty`.
3080 pub fn lazyAbiSize(ty: Type, target: Target, arena: Allocator) !Value {
3081 switch (try ty.abiSizeAdvanced(target, .{ .lazy = arena })) {
3082 .val => |val| return val,
3083 .scalar => |x| return Value.Tag.int_u64.create(arena, x),
3084 }
3085 }
3086
30793087 /// Asserts the type has the ABI size already resolved.
30803088 /// Types that return false for hasRuntimeBits() return 0.
3081 pub fn abiSize(self: Type, target: Target) u64 {
3082 return switch (self.tag()) {
3089 pub fn abiSize(ty: Type, target: Target) u64 {
3090 return (abiSizeAdvanced(ty, target, .eager) catch unreachable).scalar;
3091 }
3092
3093 const AbiSizeAdvanced = union(enum) {
3094 scalar: u64,
3095 val: Value,
3096 };
3097
3098 /// If you pass `eager` you will get back `scalar` and assert the type is resolved.
3099 /// In this case there will be no error, guaranteed.
3100 /// If you pass `lazy` you may get back `scalar` or `val`.
3101 /// If `val` is returned, a reference to `ty` has been captured.
3102 /// If you pass `sema_kit` you will get back `scalar` and resolve the type if
3103 /// necessary, possibly returning a CompileError.
3104 pub fn abiSizeAdvanced(
3105 ty: Type,
3106 target: Target,
3107 strat: AbiAlignmentAdvancedStrat,
3108 ) Module.CompileError!AbiSizeAdvanced {
3109 switch (ty.tag()) {
30833110 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
30843111 .fn_void_no_args => unreachable, // represents machine code; not a pointer
30853112 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
......@@ -3109,32 +3136,59 @@ pub const Type = extern union {
31093136 .empty_struct_literal,
31103137 .empty_struct,
31113138 .void,
3112 => 0,
3139 => return AbiSizeAdvanced{ .scalar = 0 },
31133140
3114 .@"struct", .tuple, .anon_struct => switch (self.containerLayout()) {
3141 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
31153142 .Packed => {
3116 const struct_obj = self.castTag(.@"struct").?.data;
3143 const struct_obj = ty.castTag(.@"struct").?.data;
3144 switch (strat) {
3145 .sema_kit => |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty),
3146 .lazy => |arena| {
3147 if (!struct_obj.haveFieldTypes()) {
3148 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3149 }
3150 },
3151 .eager => {},
3152 }
31173153 var buf: Type.Payload.Bits = undefined;
31183154 const int_ty = struct_obj.packedIntegerType(target, &buf);
3119 return int_ty.abiSize(target);
3155 return AbiSizeAdvanced{ .scalar = int_ty.abiSize(target) };
31203156 },
31213157 else => {
3122 const field_count = self.structFieldCount();
3158 switch (strat) {
3159 .sema_kit => |sk| try sk.sema.resolveTypeLayout(sk.block, sk.src, ty),
3160 .lazy => |arena| {
3161 if (ty.castTag(.@"struct")) |payload| {
3162 const struct_obj = payload.data;
3163 if (!struct_obj.haveLayout()) {
3164 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3165 }
3166 }
3167 },
3168 .eager => {},
3169 }
3170 const field_count = ty.structFieldCount();
31233171 if (field_count == 0) {
3124 return 0;
3172 return AbiSizeAdvanced{ .scalar = 0 };
31253173 }
3126 return self.structFieldOffset(field_count, target);
3174 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, target) };
31273175 },
31283176 },
31293177
31303178 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
31313179 var buffer: Payload.Bits = undefined;
3132 const int_tag_ty = self.intTagType(&buffer);
3133 return int_tag_ty.abiSize(target);
3180 const int_tag_ty = ty.intTagType(&buffer);
3181 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(target) };
3182 },
3183 .@"union" => {
3184 const union_obj = ty.castTag(.@"union").?.data;
3185 // TODO pass `true` for have_tag when unions have a safety tag
3186 return abiSizeAdvancedUnion(ty, target, strat, union_obj, false);
3187 },
3188 .union_tagged => {
3189 const union_obj = ty.castTag(.union_tagged).?.data;
3190 return abiSizeAdvancedUnion(ty, target, strat, union_obj, true);
31343191 },
3135 // TODO pass `true` for have_tag when unions have a safety tag
3136 .@"union" => return self.castTag(.@"union").?.data.abiSize(target, false),
3137 .union_tagged => return self.castTag(.union_tagged).?.data.abiSize(target, true),
31383192
31393193 .u1,
31403194 .u8,
......@@ -3146,21 +3200,31 @@ pub const Type = extern union {
31463200 .address_space,
31473201 .float_mode,
31483202 .reduce_op,
3149 => return 1,
3203 => return AbiSizeAdvanced{ .scalar = 1 },
31503204
3151 .array_u8 => self.castTag(.array_u8).?.data,
3152 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
3205 .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data },
3206 .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 },
31533207 .array, .vector => {
3154 const payload = self.cast(Payload.Array).?.data;
3155 const elem_size = payload.elem_type.abiSize(target);
3156 assert(elem_size >= payload.elem_type.abiAlignment(target));
3157 return payload.len * elem_size;
3208 const payload = ty.cast(Payload.Array).?.data;
3209 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
3210 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
3211 .val => switch (strat) {
3212 .sema_kit => unreachable,
3213 .eager => unreachable,
3214 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3215 },
3216 }
31583217 },
31593218 .array_sentinel => {
3160 const payload = self.castTag(.array_sentinel).?.data;
3161 const elem_size = payload.elem_type.abiSize(target);
3162 assert(elem_size >= payload.elem_type.abiAlignment(target));
3163 return (payload.len + 1) * elem_size;
3219 const payload = ty.castTag(.array_sentinel).?.data;
3220 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
3221 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size },
3222 .val => switch (strat) {
3223 .sema_kit => unreachable,
3224 .eager => unreachable,
3225 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3226 },
3227 }
31643228 },
31653229
31663230 .isize,
......@@ -3178,95 +3242,96 @@ pub const Type = extern union {
31783242 .manyptr_u8,
31793243 .manyptr_const_u8,
31803244 .manyptr_const_u8_sentinel_0,
3181 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
3245 => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
31823246
31833247 .const_slice,
31843248 .mut_slice,
31853249 .const_slice_u8,
31863250 .const_slice_u8_sentinel_0,
3187 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
3251 => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2 },
31883252
3189 .pointer => switch (self.castTag(.pointer).?.data.size) {
3190 .Slice => @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
3191 else => @divExact(target.cpu.arch.ptrBitWidth(), 8),
3253 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3254 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2 },
3255 else => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
31923256 },
31933257
3194 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
3195 .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
3196 .c_int => return @divExact(CType.int.sizeInBits(target), 8),
3197 .c_uint => return @divExact(CType.uint.sizeInBits(target), 8),
3198 .c_long => return @divExact(CType.long.sizeInBits(target), 8),
3199 .c_ulong => return @divExact(CType.ulong.sizeInBits(target), 8),
3200 .c_longlong => return @divExact(CType.longlong.sizeInBits(target), 8),
3201 .c_ulonglong => return @divExact(CType.ulonglong.sizeInBits(target), 8),
3258 .c_short => return AbiSizeAdvanced{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },
3259 .c_ushort => return AbiSizeAdvanced{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },
3260 .c_int => return AbiSizeAdvanced{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },
3261 .c_uint => return AbiSizeAdvanced{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },
3262 .c_long => return AbiSizeAdvanced{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },
3263 .c_ulong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },
3264 .c_longlong => return AbiSizeAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
3265 .c_ulonglong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 8) },
32023266
3203 .f16 => return 2,
3204 .f32 => return 4,
3205 .f64 => return 8,
3206 .f128 => return 16,
3267 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
3268 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
3269 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
3270 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
32073271
32083272 .f80 => switch (target.cpu.arch) {
3209 .i386 => return 12,
3210 .x86_64 => return 16,
3273 .i386 => return AbiSizeAdvanced{ .scalar = 12 },
3274 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
32113275 else => {
32123276 var payload: Payload.Bits = .{
32133277 .base = .{ .tag = .int_unsigned },
32143278 .data = 80,
32153279 };
32163280 const u80_ty = initPayload(&payload.base);
3217 return abiSize(u80_ty, target);
3281 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) };
32183282 },
32193283 },
32203284 .c_longdouble => switch (CType.longdouble.sizeInBits(target)) {
3221 16 => return abiSize(Type.f16, target),
3222 32 => return abiSize(Type.f32, target),
3223 64 => return abiSize(Type.f64, target),
3224 80 => return abiSize(Type.f80, target),
3225 128 => return abiSize(Type.f128, target),
3285 16 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f16, target) },
3286 32 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f32, target) },
3287 64 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f64, target) },
3288 80 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f80, target) },
3289 128 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f128, target) },
32263290 else => unreachable,
32273291 },
32283292
3293 // TODO revisit this when we have the concept of the error tag type
32293294 .error_set,
32303295 .error_set_single,
32313296 .anyerror_void_error_union,
32323297 .anyerror,
32333298 .error_set_inferred,
32343299 .error_set_merged,
3235 => return 2, // TODO revisit this when we have the concept of the error tag type
3300 => return AbiSizeAdvanced{ .scalar = 2 },
32363301
3237 .i16, .u16 => return intAbiSize(16, target),
3238 .i32, .u32 => return intAbiSize(32, target),
3239 .i64, .u64 => return intAbiSize(64, target),
3240 .u128, .i128 => return intAbiSize(128, target),
3302 .i16, .u16 => return AbiSizeAdvanced{ .scalar = intAbiSize(16, target) },
3303 .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) },
3304 .i64, .u64 => return AbiSizeAdvanced{ .scalar = intAbiSize(64, target) },
3305 .u128, .i128 => return AbiSizeAdvanced{ .scalar = intAbiSize(128, target) },
32413306 .int_signed, .int_unsigned => {
3242 const bits: u16 = self.cast(Payload.Bits).?.data;
3243 if (bits == 0) return 0;
3244 return intAbiSize(bits, target);
3307 const bits: u16 = ty.cast(Payload.Bits).?.data;
3308 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
3309 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
32453310 },
32463311
32473312 .optional => {
32483313 var buf: Payload.ElemType = undefined;
3249 const child_type = self.optionalChild(&buf);
3250 if (!child_type.hasRuntimeBits()) return 1;
3314 const child_type = ty.optionalChild(&buf);
3315 if (!child_type.hasRuntimeBits()) return AbiSizeAdvanced{ .scalar = 1 };
32513316
32523317 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr() and !child_type.isSlice())
3253 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
3318 return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
32543319
32553320 // Optional types are represented as a struct with the child type as the first
32563321 // field and a boolean as the second. Since the child type's abi alignment is
32573322 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
32583323 // to the child type's ABI alignment.
3259 return child_type.abiAlignment(target) + child_type.abiSize(target);
3324 return AbiSizeAdvanced{ .scalar = child_type.abiAlignment(target) + child_type.abiSize(target) };
32603325 },
32613326
32623327 .error_union => {
3263 const data = self.castTag(.error_union).?.data;
3328 const data = ty.castTag(.error_union).?.data;
32643329 if (!data.error_set.hasRuntimeBits() and !data.payload.hasRuntimeBits()) {
3265 return 0;
3330 return AbiSizeAdvanced{ .scalar = 0 };
32663331 } else if (!data.error_set.hasRuntimeBits()) {
3267 return data.payload.abiSize(target);
3332 return AbiSizeAdvanced{ .scalar = data.payload.abiSize(target) };
32683333 } else if (!data.payload.hasRuntimeBits()) {
3269 return data.error_set.abiSize(target);
3334 return AbiSizeAdvanced{ .scalar = data.error_set.abiSize(target) };
32703335 }
32713336 const code_align = abiAlignment(data.error_set, target);
32723337 const payload_align = abiAlignment(data.payload, target);
......@@ -3278,9 +3343,28 @@ pub const Type = extern union {
32783343 size = std.mem.alignForwardGeneric(u64, size, payload_align);
32793344 size += payload_size;
32803345 size = std.mem.alignForwardGeneric(u64, size, big_align);
3281 return size;
3346 return AbiSizeAdvanced{ .scalar = size };
32823347 },
3283 };
3348 }
3349 }
3350
3351 pub fn abiSizeAdvancedUnion(
3352 ty: Type,
3353 target: Target,
3354 strat: AbiAlignmentAdvancedStrat,
3355 union_obj: *Module.Union,
3356 have_tag: bool,
3357 ) Module.CompileError!AbiSizeAdvanced {
3358 switch (strat) {
3359 .sema_kit => |sk| try sk.sema.resolveTypeLayout(sk.block, sk.src, ty),
3360 .lazy => |arena| {
3361 if (!union_obj.haveLayout()) {
3362 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3363 }
3364 },
3365 .eager => {},
3366 }
3367 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(target, have_tag) };
32843368 }
32853369
32863370 fn intAbiSize(bits: u16, target: Target) u64 {
......@@ -5448,73 +5532,6 @@ pub const Type = extern union {
54485532 }
54495533 }
54505534
5451 /// Asserts the type is an enum.
5452 pub fn enumHasInt(ty: Type, int: Value, mod: *Module) bool {
5453 const S = struct {
5454 fn intInRange(tag_ty: Type, int_val: Value, end: usize, m: *Module) bool {
5455 if (int_val.compareWithZero(.lt)) return false;
5456 var end_payload: Value.Payload.U64 = .{
5457 .base = .{ .tag = .int_u64 },
5458 .data = end,
5459 };
5460 const end_val = Value.initPayload(&end_payload.base);
5461 if (int_val.compare(.gte, end_val, tag_ty, m)) return false;
5462 return true;
5463 }
5464 };
5465 switch (ty.tag()) {
5466 .enum_nonexhaustive => return int.intFitsInType(ty, mod.getTarget()),
5467 .enum_full => {
5468 const enum_full = ty.castTag(.enum_full).?.data;
5469 const tag_ty = enum_full.tag_ty;
5470 if (enum_full.values.count() == 0) {
5471 return S.intInRange(tag_ty, int, enum_full.fields.count(), mod);
5472 } else {
5473 return enum_full.values.containsContext(int, .{
5474 .ty = tag_ty,
5475 .mod = mod,
5476 });
5477 }
5478 },
5479 .enum_numbered => {
5480 const enum_obj = ty.castTag(.enum_numbered).?.data;
5481 const tag_ty = enum_obj.tag_ty;
5482 if (enum_obj.values.count() == 0) {
5483 return S.intInRange(tag_ty, int, enum_obj.fields.count(), mod);
5484 } else {
5485 return enum_obj.values.containsContext(int, .{
5486 .ty = tag_ty,
5487 .mod = mod,
5488 });
5489 }
5490 },
5491 .enum_simple => {
5492 const enum_simple = ty.castTag(.enum_simple).?.data;
5493 const fields_len = enum_simple.fields.count();
5494 const bits = std.math.log2_int_ceil(usize, fields_len);
5495 var buffer: Payload.Bits = .{
5496 .base = .{ .tag = .int_unsigned },
5497 .data = bits,
5498 };
5499 const tag_ty = Type.initPayload(&buffer.base);
5500 return S.intInRange(tag_ty, int, fields_len, mod);
5501 },
5502 .atomic_order,
5503 .atomic_rmw_op,
5504 .calling_convention,
5505 .address_space,
5506 .float_mode,
5507 .reduce_op,
5508 .call_options,
5509 .prefetch_options,
5510 .export_options,
5511 .extern_options,
5512 => unreachable,
5513
5514 else => unreachable,
5515 }
5516 }
5517
55185535 /// This enum does not directly correspond to `std.builtin.TypeId` because
55195536 /// it has extra enum tags in it, as a way of using less memory. For example,
55205537 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
src/value.zig+84-540
......@@ -179,6 +179,8 @@ pub const Value = extern union {
179179 bound_fn,
180180 /// The ABI alignment of the payload type.
181181 lazy_align,
182 /// The ABI alignment of the payload type.
183 lazy_size,
182184
183185 pub const last_no_payload_tag = Tag.empty_array;
184186 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -289,6 +291,7 @@ pub const Value = extern union {
289291
290292 .ty,
291293 .lazy_align,
294 .lazy_size,
292295 => Payload.Ty,
293296
294297 .int_type => Payload.IntType,
......@@ -460,7 +463,7 @@ pub const Value = extern union {
460463 .bound_fn,
461464 => unreachable,
462465
463 .ty, .lazy_align => {
466 .ty, .lazy_align, .lazy_size => {
464467 const payload = self.cast(Payload.Ty).?;
465468 const new_payload = try arena.create(Payload.Ty);
466469 new_payload.* = .{
......@@ -720,6 +723,11 @@ pub const Value = extern union {
720723 try val.castTag(.lazy_align).?.data.dump("", options, out_stream);
721724 return try out_stream.writeAll(")");
722725 },
726 .lazy_size => {
727 try out_stream.writeAll("@sizeOf(");
728 try val.castTag(.lazy_size).?.data.dump("", options, out_stream);
729 return try out_stream.writeAll(")");
730 },
723731 .int_type => {
724732 const int_type = val.castTag(.int_type).?.data;
725733 return out_stream.print("{s}{d}", .{
......@@ -1040,6 +1048,14 @@ pub const Value = extern union {
10401048 const x = ty.abiAlignment(target);
10411049 return BigIntMutable.init(&space.limbs, x).toConst();
10421050 },
1051 .lazy_size => {
1052 const ty = val.castTag(.lazy_size).?.data;
1053 if (sema_kit) |sk| {
1054 try sk.sema.resolveTypeLayout(sk.block, sk.src, ty);
1055 }
1056 const x = ty.abiSize(target);
1057 return BigIntMutable.init(&space.limbs, x).toConst();
1058 },
10431059
10441060 .elem_ptr => {
10451061 const elem_ptr = val.castTag(.elem_ptr).?.data;
......@@ -1087,6 +1103,14 @@ pub const Value = extern union {
10871103 return ty.abiAlignment(target);
10881104 }
10891105 },
1106 .lazy_size => {
1107 const ty = val.castTag(.lazy_size).?.data;
1108 if (sema_kit) |sk| {
1109 return (try ty.abiSizeAdvanced(target, .{ .sema_kit = sk })).scalar;
1110 } else {
1111 return ty.abiSize(target);
1112 }
1113 },
10901114
10911115 else => return null,
10921116 }
......@@ -1670,118 +1694,6 @@ pub const Value = extern union {
16701694 }
16711695 }
16721696
1673 /// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
1674 /// Vectors are also accepted. Vector results are reduced with AND.
1675 pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
1676 switch (self.tag()) {
1677 .zero,
1678 .undef,
1679 .bool_false,
1680 => return true,
1681
1682 .one,
1683 .bool_true,
1684 => switch (ty.zigTypeTag()) {
1685 .Int => {
1686 const info = ty.intInfo(target);
1687 return switch (info.signedness) {
1688 .signed => info.bits >= 2,
1689 .unsigned => info.bits >= 1,
1690 };
1691 },
1692 .ComptimeInt => return true,
1693 else => unreachable,
1694 },
1695
1696 .lazy_align => {
1697 const info = ty.intInfo(target);
1698 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
1699 // If it is u16 or bigger we know the alignment fits without resolving it.
1700 if (info.bits >= max_needed_bits) return true;
1701 const x = self.castTag(.lazy_align).?.data.abiAlignment(target);
1702 if (x == 0) return true;
1703 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
1704 return info.bits >= actual_needed_bits;
1705 },
1706
1707 .int_u64 => switch (ty.zigTypeTag()) {
1708 .Int => {
1709 const x = self.castTag(.int_u64).?.data;
1710 if (x == 0) return true;
1711 const info = ty.intInfo(target);
1712 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
1713 return info.bits >= needed_bits;
1714 },
1715 .ComptimeInt => return true,
1716 else => unreachable,
1717 },
1718 .int_i64 => switch (ty.zigTypeTag()) {
1719 .Int => {
1720 const x = self.castTag(.int_i64).?.data;
1721 if (x == 0) return true;
1722 const info = ty.intInfo(target);
1723 if (info.signedness == .unsigned and x < 0)
1724 return false;
1725 var buffer: BigIntSpace = undefined;
1726 return self.toBigInt(&buffer, target).fitsInTwosComp(info.signedness, info.bits);
1727 },
1728 .ComptimeInt => return true,
1729 else => unreachable,
1730 },
1731 .int_big_positive => switch (ty.zigTypeTag()) {
1732 .Int => {
1733 const info = ty.intInfo(target);
1734 return self.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
1735 },
1736 .ComptimeInt => return true,
1737 else => unreachable,
1738 },
1739 .int_big_negative => switch (ty.zigTypeTag()) {
1740 .Int => {
1741 const info = ty.intInfo(target);
1742 return self.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
1743 },
1744 .ComptimeInt => return true,
1745 else => unreachable,
1746 },
1747
1748 .the_only_possible_value => {
1749 assert(ty.intInfo(target).bits == 0);
1750 return true;
1751 },
1752
1753 .decl_ref_mut,
1754 .extern_fn,
1755 .decl_ref,
1756 .function,
1757 .variable,
1758 => switch (ty.zigTypeTag()) {
1759 .Int => {
1760 const info = ty.intInfo(target);
1761 const ptr_bits = target.cpu.arch.ptrBitWidth();
1762 return switch (info.signedness) {
1763 .signed => info.bits > ptr_bits,
1764 .unsigned => info.bits >= ptr_bits,
1765 };
1766 },
1767 .ComptimeInt => return true,
1768 else => unreachable,
1769 },
1770
1771 .aggregate => {
1772 assert(ty.zigTypeTag() == .Vector);
1773 for (self.castTag(.aggregate).?.data) |elem| {
1774 if (!elem.intFitsInType(ty.scalarType(), target)) {
1775 return false;
1776 }
1777 }
1778 return true;
1779 },
1780
1781 else => unreachable,
1782 }
1783 }
1784
17851697 /// Converts an integer or a float to a float. May result in a loss of information.
17861698 /// Caller can find out by equality checking the result against the operand.
17871699 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
......@@ -1849,6 +1761,14 @@ pub const Value = extern union {
18491761 return .eq;
18501762 }
18511763 },
1764 .lazy_size => {
1765 const ty = lhs.castTag(.lazy_size).?.data;
1766 if (try ty.hasRuntimeBitsAdvanced(false, sema_kit)) {
1767 return .gt;
1768 } else {
1769 return .eq;
1770 }
1771 },
18521772
18531773 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
18541774 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
......@@ -1992,38 +1912,28 @@ pub const Value = extern union {
19921912 };
19931913 }
19941914
1995 /// Asserts the values are comparable vectors of type `ty`.
1996 pub fn compareVector(
1997 lhs: Value,
1998 op: std.math.CompareOperator,
1999 rhs: Value,
2000 ty: Type,
2001 allocator: Allocator,
2002 mod: *Module,
2003 ) !Value {
2004 assert(ty.zigTypeTag() == .Vector);
2005 const result_data = try allocator.alloc(Value, ty.vectorLen());
2006 for (result_data) |*scalar, i| {
2007 const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType(), mod);
2008 scalar.* = makeBool(res_bool);
2009 }
2010 return Value.Tag.aggregate.create(allocator, result_data);
2011 }
2012
20131915 /// Asserts the value is comparable.
20141916 /// Vector results will be reduced with AND.
20151917 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
1918 return compareWithZeroAdvanced(lhs, op, null) catch unreachable;
1919 }
1920
1921 pub fn compareWithZeroAdvanced(
1922 lhs: Value,
1923 op: std.math.CompareOperator,
1924 sema_kit: ?Module.WipAnalysis,
1925 ) Module.CompileError!bool {
20161926 switch (lhs.tag()) {
2017 .repeated => return lhs.castTag(.repeated).?.data.compareWithZero(op),
1927 .repeated => return lhs.castTag(.repeated).?.data.compareWithZeroAdvanced(op, sema_kit),
20181928 .aggregate => {
20191929 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2020 if (!elem_val.compareWithZero(op)) return false;
1930 if (!(try elem_val.compareWithZeroAdvanced(op, sema_kit))) return false;
20211931 }
20221932 return true;
20231933 },
20241934 else => {},
20251935 }
2026 return orderAgainstZero(lhs).compare(op);
1936 return (try orderAgainstZeroAdvanced(lhs, sema_kit)).compare(op);
20271937 }
20281938
20291939 /// This function is used by hash maps and so treats floating-point NaNs as equal
......@@ -2032,9 +1942,20 @@ pub const Value = extern union {
20321942 /// This function has to be able to support implicit coercion of `a` to `ty`. That is,
20331943 /// `ty` will be an exactly correct Type for `b` but it may be a post-coerced Type
20341944 /// for `a`. This function must act *as if* `a` has been coerced to `ty`. This complication
2035 /// is required in order to make generic function instantiation effecient - specifically
1945 /// is required in order to make generic function instantiation efficient - specifically
20361946 /// the insertion into the monomorphized function table.
20371947 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
1948 return eqlAdvanced(a, b, ty, mod, null) catch unreachable;
1949 }
1950
1951 /// If `null` is provided for `sema_kit` then it is guaranteed no error will be returned.
1952 pub fn eqlAdvanced(
1953 a: Value,
1954 b: Value,
1955 ty: Type,
1956 mod: *Module,
1957 sema_kit: ?Module.WipAnalysis,
1958 ) Module.CompileError!bool {
20381959 const target = mod.getTarget();
20391960 const a_tag = a.tag();
20401961 const b_tag = b.tag();
......@@ -2055,31 +1976,33 @@ pub const Value = extern union {
20551976 const a_payload = a.castTag(.opt_payload).?.data;
20561977 const b_payload = b.castTag(.opt_payload).?.data;
20571978 var buffer: Type.Payload.ElemType = undefined;
2058 return eql(a_payload, b_payload, ty.optionalChild(&buffer), mod);
1979 return eqlAdvanced(a_payload, b_payload, ty.optionalChild(&buffer), mod, sema_kit);
20591980 },
20601981 .slice => {
20611982 const a_payload = a.castTag(.slice).?.data;
20621983 const b_payload = b.castTag(.slice).?.data;
2063 if (!eql(a_payload.len, b_payload.len, Type.usize, mod)) return false;
1984 if (!(try eqlAdvanced(a_payload.len, b_payload.len, Type.usize, mod, sema_kit))) {
1985 return false;
1986 }
20641987
20651988 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
20661989 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
20671990
2068 return eql(a_payload.ptr, b_payload.ptr, ptr_ty, mod);
1991 return eqlAdvanced(a_payload.ptr, b_payload.ptr, ptr_ty, mod, sema_kit);
20691992 },
20701993 .elem_ptr => {
20711994 const a_payload = a.castTag(.elem_ptr).?.data;
20721995 const b_payload = b.castTag(.elem_ptr).?.data;
20731996 if (a_payload.index != b_payload.index) return false;
20741997
2075 return eql(a_payload.array_ptr, b_payload.array_ptr, ty, mod);
1998 return eqlAdvanced(a_payload.array_ptr, b_payload.array_ptr, ty, mod, sema_kit);
20761999 },
20772000 .field_ptr => {
20782001 const a_payload = a.castTag(.field_ptr).?.data;
20792002 const b_payload = b.castTag(.field_ptr).?.data;
20802003 if (a_payload.field_index != b_payload.field_index) return false;
20812004
2082 return eql(a_payload.container_ptr, b_payload.container_ptr, ty, mod);
2005 return eqlAdvanced(a_payload.container_ptr, b_payload.container_ptr, ty, mod, sema_kit);
20832006 },
20842007 .@"error" => {
20852008 const a_name = a.castTag(.@"error").?.data.name;
......@@ -2089,7 +2012,7 @@ pub const Value = extern union {
20892012 .eu_payload => {
20902013 const a_payload = a.castTag(.eu_payload).?.data;
20912014 const b_payload = b.castTag(.eu_payload).?.data;
2092 return eql(a_payload, b_payload, ty.errorUnionPayload(), mod);
2015 return eqlAdvanced(a_payload, b_payload, ty.errorUnionPayload(), mod, sema_kit);
20932016 },
20942017 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
20952018 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
......@@ -2107,7 +2030,9 @@ pub const Value = extern union {
21072030 const types = ty.tupleFields().types;
21082031 assert(types.len == a_field_vals.len);
21092032 for (types) |field_ty, i| {
2110 if (!eql(a_field_vals[i], b_field_vals[i], field_ty, mod)) return false;
2033 if (!(try eqlAdvanced(a_field_vals[i], b_field_vals[i], field_ty, mod, sema_kit))) {
2034 return false;
2035 }
21112036 }
21122037 return true;
21132038 }
......@@ -2116,7 +2041,9 @@ pub const Value = extern union {
21162041 const fields = ty.structFields().values();
21172042 assert(fields.len == a_field_vals.len);
21182043 for (fields) |field, i| {
2119 if (!eql(a_field_vals[i], b_field_vals[i], field.ty, mod)) return false;
2044 if (!(try eqlAdvanced(a_field_vals[i], b_field_vals[i], field.ty, mod, sema_kit))) {
2045 return false;
2046 }
21202047 }
21212048 return true;
21222049 }
......@@ -2125,7 +2052,9 @@ pub const Value = extern union {
21252052 for (a_field_vals) |a_elem, i| {
21262053 const b_elem = b_field_vals[i];
21272054
2128 if (!eql(a_elem, b_elem, elem_ty, mod)) return false;
2055 if (!(try eqlAdvanced(a_elem, b_elem, elem_ty, mod, sema_kit))) {
2056 return false;
2057 }
21292058 }
21302059 return true;
21312060 },
......@@ -2135,7 +2064,7 @@ pub const Value = extern union {
21352064 switch (ty.containerLayout()) {
21362065 .Packed, .Extern => {
21372066 const tag_ty = ty.unionTagTypeHypothetical();
2138 if (!a_union.tag.eql(b_union.tag, tag_ty, mod)) {
2067 if (!(try a_union.tag.eqlAdvanced(b_union.tag, tag_ty, mod, sema_kit))) {
21392068 // In this case, we must disregard mismatching tags and compare
21402069 // based on the in-memory bytes of the payloads.
21412070 @panic("TODO comptime comparison of extern union values with mismatching tags");
......@@ -2143,13 +2072,13 @@ pub const Value = extern union {
21432072 },
21442073 .Auto => {
21452074 const tag_ty = ty.unionTagTypeHypothetical();
2146 if (!a_union.tag.eql(b_union.tag, tag_ty, mod)) {
2075 if (!(try a_union.tag.eqlAdvanced(b_union.tag, tag_ty, mod, sema_kit))) {
21472076 return false;
21482077 }
21492078 },
21502079 }
21512080 const active_field_ty = ty.unionFieldType(a_union.tag, mod);
2152 return a_union.val.eql(b_union.val, active_field_ty, mod);
2081 return a_union.val.eqlAdvanced(b_union.val, active_field_ty, mod, sema_kit);
21532082 },
21542083 else => {},
21552084 } else if (a_tag == .null_value or b_tag == .null_value) {
......@@ -2183,7 +2112,7 @@ pub const Value = extern union {
21832112 const b_val = b.enumToInt(ty, &buf_b);
21842113 var buf_ty: Type.Payload.Bits = undefined;
21852114 const int_ty = ty.intTagType(&buf_ty);
2186 return eql(a_val, b_val, int_ty, mod);
2115 return eqlAdvanced(a_val, b_val, int_ty, mod, sema_kit);
21872116 },
21882117 .Array, .Vector => {
21892118 const len = ty.arrayLen();
......@@ -2194,7 +2123,9 @@ pub const Value = extern union {
21942123 while (i < len) : (i += 1) {
21952124 const a_elem = elemValueBuffer(a, mod, i, &a_buf);
21962125 const b_elem = elemValueBuffer(b, mod, i, &b_buf);
2197 if (!eql(a_elem, b_elem, elem_ty, mod)) return false;
2126 if (!(try eqlAdvanced(a_elem, b_elem, elem_ty, mod, sema_kit))) {
2127 return false;
2128 }
21982129 }
21992130 return true;
22002131 },
......@@ -2218,12 +2149,12 @@ pub const Value = extern union {
22182149 .base = .{ .tag = .opt_payload },
22192150 .data = a,
22202151 };
2221 return eql(Value.initPayload(&buffer.base), b, ty, mod);
2152 return eqlAdvanced(Value.initPayload(&buffer.base), b, ty, mod, sema_kit);
22222153 }
22232154 },
22242155 else => {},
22252156 }
2226 return order(a, b, target).compare(.eq);
2157 return (try orderAdvanced(a, b, target, sema_kit)).compare(.eq);
22272158 }
22282159
22292160 /// This function is used by hash maps and so treats floating-point NaNs as equal
......@@ -2502,6 +2433,7 @@ pub const Value = extern union {
25022433 .bool_true,
25032434 .the_only_possible_value,
25042435 .lazy_align,
2436 .lazy_size,
25052437 => return hashInt(ptr_val, hasher, target),
25062438
25072439 else => unreachable,
......@@ -2882,54 +2814,6 @@ pub const Value = extern union {
28822814 }
28832815 }
28842816
2885 pub fn floatToInt(val: Value, arena: Allocator, float_ty: Type, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
2886 if (float_ty.zigTypeTag() == .Vector) {
2887 const result_data = try arena.alloc(Value, float_ty.vectorLen());
2888 for (result_data) |*scalar, i| {
2889 scalar.* = try floatToIntScalar(val.indexVectorlike(i), arena, int_ty.scalarType(), target);
2890 }
2891 return Value.Tag.aggregate.create(arena, result_data);
2892 }
2893 return floatToIntScalar(val, arena, int_ty, target);
2894 }
2895
2896 pub fn floatToIntScalar(val: Value, arena: Allocator, int_ty: Type, target: Target) error{ FloatCannotFit, OutOfMemory }!Value {
2897 const Limb = std.math.big.Limb;
2898
2899 var value = val.toFloat(f64); // TODO: f128 ?
2900 if (std.math.isNan(value) or std.math.isInf(value)) {
2901 return error.FloatCannotFit;
2902 }
2903
2904 const isNegative = std.math.signbit(value);
2905 value = @fabs(value);
2906
2907 const floored = @floor(value);
2908
2909 var rational = try std.math.big.Rational.init(arena);
2910 defer rational.deinit();
2911 rational.setFloat(f64, floored) catch |err| switch (err) {
2912 error.NonFiniteFloat => unreachable,
2913 error.OutOfMemory => return error.OutOfMemory,
2914 };
2915
2916 // The float is reduced in rational.setFloat, so we assert that denominator is equal to one
2917 const bigOne = std.math.big.int.Const{ .limbs = &.{1}, .positive = true };
2918 assert(rational.q.toConst().eqAbs(bigOne));
2919
2920 const result_limbs = try arena.dupe(Limb, rational.p.toConst().limbs);
2921 const result = if (isNegative)
2922 try Value.Tag.int_big_negative.create(arena, result_limbs)
2923 else
2924 try Value.Tag.int_big_positive.create(arena, result_limbs);
2925
2926 if (result.intFitsInType(int_ty, target)) {
2927 return result;
2928 } else {
2929 return error.FloatCannotFit;
2930 }
2931 }
2932
29332817 fn calcLimbLenFloat(scalar: anytype) usize {
29342818 if (scalar == 0) {
29352819 return 1;
......@@ -2945,96 +2829,7 @@ pub const Value = extern union {
29452829 wrapped_result: Value,
29462830 };
29472831
2948 pub fn intAddWithOverflow(
2949 lhs: Value,
2950 rhs: Value,
2951 ty: Type,
2952 arena: Allocator,
2953 target: Target,
2954 ) !OverflowArithmeticResult {
2955 if (ty.zigTypeTag() == .Vector) {
2956 const overflowed_data = try arena.alloc(Value, ty.vectorLen());
2957 const result_data = try arena.alloc(Value, ty.vectorLen());
2958 for (result_data) |*scalar, i| {
2959 const of_math_result = try intAddWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
2960 overflowed_data[i] = of_math_result.overflowed;
2961 scalar.* = of_math_result.wrapped_result;
2962 }
2963 return OverflowArithmeticResult{
2964 .overflowed = try Value.Tag.aggregate.create(arena, overflowed_data),
2965 .wrapped_result = try Value.Tag.aggregate.create(arena, result_data),
2966 };
2967 }
2968 return intAddWithOverflowScalar(lhs, rhs, ty, arena, target);
2969 }
2970
2971 pub fn intAddWithOverflowScalar(
2972 lhs: Value,
2973 rhs: Value,
2974 ty: Type,
2975 arena: Allocator,
2976 target: Target,
2977 ) !OverflowArithmeticResult {
2978 const info = ty.intInfo(target);
2979
2980 var lhs_space: Value.BigIntSpace = undefined;
2981 var rhs_space: Value.BigIntSpace = undefined;
2982 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
2983 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2984 const limbs = try arena.alloc(
2985 std.math.big.Limb,
2986 std.math.big.int.calcTwosCompLimbCount(info.bits),
2987 );
2988 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
2989 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
2990 const result = try fromBigInt(arena, result_bigint.toConst());
2991 return OverflowArithmeticResult{
2992 .overflowed = makeBool(overflowed),
2993 .wrapped_result = result,
2994 };
2995 }
2996
2997 /// Supports both (vectors of) floats and ints; handles undefined scalars.
2998 pub fn numberAddWrap(
2999 lhs: Value,
3000 rhs: Value,
3001 ty: Type,
3002 arena: Allocator,
3003 target: Target,
3004 ) !Value {
3005 if (ty.zigTypeTag() == .Vector) {
3006 const result_data = try arena.alloc(Value, ty.vectorLen());
3007 for (result_data) |*scalar, i| {
3008 scalar.* = try numberAddWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3009 }
3010 return Value.Tag.aggregate.create(arena, result_data);
3011 }
3012 return numberAddWrapScalar(lhs, rhs, ty, arena, target);
3013 }
3014
3015 /// Supports both floats and ints; handles undefined.
3016 pub fn numberAddWrapScalar(
3017 lhs: Value,
3018 rhs: Value,
3019 ty: Type,
3020 arena: Allocator,
3021 target: Target,
3022 ) !Value {
3023 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
3024
3025 if (ty.zigTypeTag() == .ComptimeInt) {
3026 return intAdd(lhs, rhs, ty, arena, target);
3027 }
3028
3029 if (ty.isAnyFloat()) {
3030 return floatAdd(lhs, rhs, ty, arena, target);
3031 }
3032
3033 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
3034 return overflow_result.wrapped_result;
3035 }
3036
3037 fn fromBigInt(arena: Allocator, big_int: BigIntConst) !Value {
2832 pub fn fromBigInt(arena: Allocator, big_int: BigIntConst) !Value {
30382833 if (big_int.positive) {
30392834 if (big_int.to(u64)) |x| {
30402835 return Value.Tag.int_u64.create(arena, x);
......@@ -3094,95 +2889,6 @@ pub const Value = extern union {
30942889 return fromBigInt(arena, result_bigint.toConst());
30952890 }
30962891
3097 pub fn intSubWithOverflow(
3098 lhs: Value,
3099 rhs: Value,
3100 ty: Type,
3101 arena: Allocator,
3102 target: Target,
3103 ) !OverflowArithmeticResult {
3104 if (ty.zigTypeTag() == .Vector) {
3105 const overflowed_data = try arena.alloc(Value, ty.vectorLen());
3106 const result_data = try arena.alloc(Value, ty.vectorLen());
3107 for (result_data) |*scalar, i| {
3108 const of_math_result = try intSubWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3109 overflowed_data[i] = of_math_result.overflowed;
3110 scalar.* = of_math_result.wrapped_result;
3111 }
3112 return OverflowArithmeticResult{
3113 .overflowed = try Value.Tag.aggregate.create(arena, overflowed_data),
3114 .wrapped_result = try Value.Tag.aggregate.create(arena, result_data),
3115 };
3116 }
3117 return intSubWithOverflowScalar(lhs, rhs, ty, arena, target);
3118 }
3119
3120 pub fn intSubWithOverflowScalar(
3121 lhs: Value,
3122 rhs: Value,
3123 ty: Type,
3124 arena: Allocator,
3125 target: Target,
3126 ) !OverflowArithmeticResult {
3127 const info = ty.intInfo(target);
3128
3129 var lhs_space: Value.BigIntSpace = undefined;
3130 var rhs_space: Value.BigIntSpace = undefined;
3131 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3132 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
3133 const limbs = try arena.alloc(
3134 std.math.big.Limb,
3135 std.math.big.int.calcTwosCompLimbCount(info.bits),
3136 );
3137 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3138 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
3139 const wrapped_result = try fromBigInt(arena, result_bigint.toConst());
3140 return OverflowArithmeticResult{
3141 .overflowed = makeBool(overflowed),
3142 .wrapped_result = wrapped_result,
3143 };
3144 }
3145
3146 /// Supports both (vectors of) floats and ints; handles undefined scalars.
3147 pub fn numberSubWrap(
3148 lhs: Value,
3149 rhs: Value,
3150 ty: Type,
3151 arena: Allocator,
3152 target: Target,
3153 ) !Value {
3154 if (ty.zigTypeTag() == .Vector) {
3155 const result_data = try arena.alloc(Value, ty.vectorLen());
3156 for (result_data) |*scalar, i| {
3157 scalar.* = try numberSubWrapScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target);
3158 }
3159 return Value.Tag.aggregate.create(arena, result_data);
3160 }
3161 return numberSubWrapScalar(lhs, rhs, ty, arena, target);
3162 }
3163
3164 /// Supports both floats and ints; handles undefined.
3165 pub fn numberSubWrapScalar(
3166 lhs: Value,
3167 rhs: Value,
3168 ty: Type,
3169 arena: Allocator,
3170 target: Target,
3171 ) !Value {
3172 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
3173
3174 if (ty.zigTypeTag() == .ComptimeInt) {
3175 return intSub(lhs, rhs, ty, arena, target);
3176 }
3177
3178 if (ty.isAnyFloat()) {
3179 return floatSub(lhs, rhs, ty, arena, target);
3180 }
3181
3182 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
3183 return overflow_result.wrapped_result;
3184 }
3185
31862892 /// Supports (vectors of) integers only; asserts neither operand is undefined.
31872893 pub fn intSubSat(
31882894 lhs: Value,
......@@ -3559,60 +3265,6 @@ pub const Value = extern union {
35593265 return fromBigInt(arena, result_bigint.toConst());
35603266 }
35613267
3562 pub fn intAdd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value {
3563 if (ty.zigTypeTag() == .Vector) {
3564 const result_data = try allocator.alloc(Value, ty.vectorLen());
3565 for (result_data) |*scalar, i| {
3566 scalar.* = try intAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator, target);
3567 }
3568 return Value.Tag.aggregate.create(allocator, result_data);
3569 }
3570 return intAddScalar(lhs, rhs, allocator, target);
3571 }
3572
3573 pub fn intAddScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
3574 // TODO is this a performance issue? maybe we should try the operation without
3575 // resorting to BigInt first.
3576 var lhs_space: Value.BigIntSpace = undefined;
3577 var rhs_space: Value.BigIntSpace = undefined;
3578 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3579 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
3580 const limbs = try allocator.alloc(
3581 std.math.big.Limb,
3582 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
3583 );
3584 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3585 result_bigint.add(lhs_bigint, rhs_bigint);
3586 return fromBigInt(allocator, result_bigint.toConst());
3587 }
3588
3589 pub fn intSub(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value {
3590 if (ty.zigTypeTag() == .Vector) {
3591 const result_data = try allocator.alloc(Value, ty.vectorLen());
3592 for (result_data) |*scalar, i| {
3593 scalar.* = try intSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator, target);
3594 }
3595 return Value.Tag.aggregate.create(allocator, result_data);
3596 }
3597 return intSubScalar(lhs, rhs, allocator, target);
3598 }
3599
3600 pub fn intSubScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
3601 // TODO is this a performance issue? maybe we should try the operation without
3602 // resorting to BigInt first.
3603 var lhs_space: Value.BigIntSpace = undefined;
3604 var rhs_space: Value.BigIntSpace = undefined;
3605 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3606 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
3607 const limbs = try allocator.alloc(
3608 std.math.big.Limb,
3609 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
3610 );
3611 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3612 result_bigint.sub(lhs_bigint, rhs_bigint);
3613 return fromBigInt(allocator, result_bigint.toConst());
3614 }
3615
36163268 pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value {
36173269 if (ty.zigTypeTag() == .Vector) {
36183270 const result_data = try allocator.alloc(Value, ty.vectorLen());
......@@ -4129,114 +3781,6 @@ pub const Value = extern union {
41293781 return fromBigInt(allocator, result_bigint.toConst());
41303782 }
41313783
4132 pub fn floatAdd(
4133 lhs: Value,
4134 rhs: Value,
4135 float_type: Type,
4136 arena: Allocator,
4137 target: Target,
4138 ) !Value {
4139 if (float_type.zigTypeTag() == .Vector) {
4140 const result_data = try arena.alloc(Value, float_type.vectorLen());
4141 for (result_data) |*scalar, i| {
4142 scalar.* = try floatAddScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4143 }
4144 return Value.Tag.aggregate.create(arena, result_data);
4145 }
4146 return floatAddScalar(lhs, rhs, float_type, arena, target);
4147 }
4148
4149 pub fn floatAddScalar(
4150 lhs: Value,
4151 rhs: Value,
4152 float_type: Type,
4153 arena: Allocator,
4154 target: Target,
4155 ) !Value {
4156 switch (float_type.floatBits(target)) {
4157 16 => {
4158 const lhs_val = lhs.toFloat(f16);
4159 const rhs_val = rhs.toFloat(f16);
4160 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
4161 },
4162 32 => {
4163 const lhs_val = lhs.toFloat(f32);
4164 const rhs_val = rhs.toFloat(f32);
4165 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
4166 },
4167 64 => {
4168 const lhs_val = lhs.toFloat(f64);
4169 const rhs_val = rhs.toFloat(f64);
4170 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
4171 },
4172 80 => {
4173 const lhs_val = lhs.toFloat(f80);
4174 const rhs_val = rhs.toFloat(f80);
4175 return Value.Tag.float_80.create(arena, lhs_val + rhs_val);
4176 },
4177 128 => {
4178 const lhs_val = lhs.toFloat(f128);
4179 const rhs_val = rhs.toFloat(f128);
4180 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
4181 },
4182 else => unreachable,
4183 }
4184 }
4185
4186 pub fn floatSub(
4187 lhs: Value,
4188 rhs: Value,
4189 float_type: Type,
4190 arena: Allocator,
4191 target: Target,
4192 ) !Value {
4193 if (float_type.zigTypeTag() == .Vector) {
4194 const result_data = try arena.alloc(Value, float_type.vectorLen());
4195 for (result_data) |*scalar, i| {
4196 scalar.* = try floatSubScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), float_type.scalarType(), arena, target);
4197 }
4198 return Value.Tag.aggregate.create(arena, result_data);
4199 }
4200 return floatSubScalar(lhs, rhs, float_type, arena, target);
4201 }
4202
4203 pub fn floatSubScalar(
4204 lhs: Value,
4205 rhs: Value,
4206 float_type: Type,
4207 arena: Allocator,
4208 target: Target,
4209 ) !Value {
4210 switch (float_type.floatBits(target)) {
4211 16 => {
4212 const lhs_val = lhs.toFloat(f16);
4213 const rhs_val = rhs.toFloat(f16);
4214 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
4215 },
4216 32 => {
4217 const lhs_val = lhs.toFloat(f32);
4218 const rhs_val = rhs.toFloat(f32);
4219 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
4220 },
4221 64 => {
4222 const lhs_val = lhs.toFloat(f64);
4223 const rhs_val = rhs.toFloat(f64);
4224 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
4225 },
4226 80 => {
4227 const lhs_val = lhs.toFloat(f80);
4228 const rhs_val = rhs.toFloat(f80);
4229 return Value.Tag.float_80.create(arena, lhs_val - rhs_val);
4230 },
4231 128 => {
4232 const lhs_val = lhs.toFloat(f128);
4233 const rhs_val = rhs.toFloat(f128);
4234 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
4235 },
4236 else => unreachable,
4237 }
4238 }
4239
42403784 pub fn floatNeg(
42413785 val: Value,
42423786 float_type: Type,
test/behavior/call.zig+9-22
......@@ -19,7 +19,11 @@ test "super basic invocations" {
1919}
2020
2121test "basic invocations" {
22 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2327
2428 const foo = struct {
2529 fn foo() i32 {
......@@ -41,7 +45,10 @@ test "basic invocations" {
4145 }
4246 {
4347 // call of non comptime-known function
44 var alias_foo = foo;
48 var alias_foo = switch (builtin.zig_backend) {
49 .stage1 => foo,
50 else => &foo,
51 };
4552 try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
4653 try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
4754 try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
......@@ -79,26 +86,6 @@ test "tuple parameters" {
7986 }
8087}
8188
82test "comptime call with bound function as parameter" {
83 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
84
85 const S = struct {
86 fn ReturnType(func: anytype) type {
87 return switch (@typeInfo(@TypeOf(func))) {
88 .BoundFn => |info| info,
89 else => unreachable,
90 }.return_type orelse void;
91 }
92
93 fn call_me_maybe() ?i32 {
94 return 123;
95 }
96 };
97
98 var inst: S = undefined;
99 try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
100}
101
10289test "result location of function call argument through runtime condition and struct init" {
10390 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/cast.zig+3-1
......@@ -630,7 +630,9 @@ test "vector casts" {
630630}
631631
632632test "@floatCast cast down" {
633 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
633 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
634 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
635 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
634636
635637 {
636638 var double: f64 = 0.001534;
test/behavior/sizeof_and_typeof.zig-2
......@@ -169,8 +169,6 @@ test "@bitOffsetOf" {
169169}
170170
171171test "@sizeOf(T) == 0 doesn't force resolving struct size" {
172 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
173
174172 const S = struct {
175173 const Foo = struct {
176174 y: if (@sizeOf(Foo) == 0) u64 else u32,