| ... | ... | @@ -3125,11 +3125,11 @@ fn zirEnumDecl( |
| 3125 | 3125 | return sema.failWithOwnedErrorMsg(msg); |
| 3126 | 3126 | } |
| 3127 | 3127 | |
| 3128 | | if (has_tag_value) { |
| 3128 | const tag_overflow = if (has_tag_value) overflow: { |
| 3129 | 3129 | const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 3130 | 3130 | extra_index += 1; |
| 3131 | 3131 | const tag_inst = try sema.resolveInst(tag_val_ref); |
| 3132 | | const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) { |
| 3132 | last_tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) { |
| 3133 | 3133 | error.NeededSourceLocation => { |
| 3134 | 3134 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3135 | 3135 | .index = field_i, |
| ... | ... | @@ -3140,43 +3140,50 @@ fn zirEnumDecl( |
| 3140 | 3140 | }, |
| 3141 | 3141 | else => |e| return e, |
| 3142 | 3142 | }; |
| 3143 | | last_tag_val = tag_val; |
| 3144 | | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, tag_val.toIntern())) |other_index| { |
| 3143 | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; |
| 3144 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); |
| 3145 | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| { |
| 3145 | 3146 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3146 | 3147 | .index = field_i, |
| 3147 | 3148 | .range = .value, |
| 3148 | 3149 | }).lazy; |
| 3149 | 3150 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; |
| 3150 | 3151 | const msg = msg: { |
| 3151 | | const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{tag_val.fmtValue(int_tag_ty, sema.mod)}); |
| 3152 | const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); |
| 3152 | 3153 | errdefer msg.destroy(gpa); |
| 3153 | 3154 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3154 | 3155 | break :msg msg; |
| 3155 | 3156 | }; |
| 3156 | 3157 | return sema.failWithOwnedErrorMsg(msg); |
| 3157 | 3158 | } |
| 3158 | | } else if (any_values) { |
| 3159 | | const tag_val = if (last_tag_val) |val| |
| 3160 | | try sema.intAdd(val, try mod.intValue(int_tag_ty, 1), int_tag_ty) |
| 3159 | break :overflow false; |
| 3160 | } else if (any_values) overflow: { |
| 3161 | var overflow: ?usize = null; |
| 3162 | last_tag_val = if (last_tag_val) |val| |
| 3163 | try sema.intAdd(val, try mod.intValue(int_tag_ty, 1), int_tag_ty, &overflow) |
| 3161 | 3164 | else |
| 3162 | 3165 | try mod.intValue(int_tag_ty, 0); |
| 3163 | | last_tag_val = tag_val; |
| 3164 | | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, tag_val.toIntern())) |other_index| { |
| 3166 | if (overflow != null) break :overflow true; |
| 3167 | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| { |
| 3165 | 3168 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; |
| 3166 | 3169 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; |
| 3167 | 3170 | const msg = msg: { |
| 3168 | | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(int_tag_ty, sema.mod)}); |
| 3171 | const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)}); |
| 3169 | 3172 | errdefer msg.destroy(gpa); |
| 3170 | 3173 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3171 | 3174 | break :msg msg; |
| 3172 | 3175 | }; |
| 3173 | 3176 | return sema.failWithOwnedErrorMsg(msg); |
| 3174 | 3177 | } |
| 3175 | | } else { |
| 3176 | | last_tag_val = try mod.intValue(int_tag_ty, field_i); |
| 3177 | | } |
| 3178 | break :overflow false; |
| 3179 | } else overflow: { |
| 3180 | last_tag_val = try mod.intValue(Type.comptime_int, field_i); |
| 3181 | if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; |
| 3182 | last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty); |
| 3183 | break :overflow false; |
| 3184 | }; |
| 3178 | 3185 | |
| 3179 | | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) { |
| 3186 | if (tag_overflow) { |
| 3180 | 3187 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3181 | 3188 | .index = field_i, |
| 3182 | 3189 | .range = if (has_tag_value) .value else .name, |
| ... | ... | @@ -9692,7 +9699,7 @@ fn intCast( |
| 9692 | 9699 | const dest_range_val = if (wanted_info.signedness == .signed) range_val: { |
| 9693 | 9700 | const one = try mod.intValue(unsigned_operand_ty, 1); |
| 9694 | 9701 | const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod); |
| 9695 | | break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty); |
| 9702 | break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty, undefined); |
| 9696 | 9703 | } else try mod.getCoerced(dest_max_val, unsigned_operand_ty); |
| 9697 | 9704 | const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val); |
| 9698 | 9705 | |
| ... | ... | @@ -11229,7 +11236,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11229 | 11236 | |
| 11230 | 11237 | while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ |
| 11231 | 11238 | // Previous validation has resolved any possible lazy values. |
| 11232 | | item = try sema.intAddScalar(item, try mod.intValue(operand_ty, 1), operand_ty); |
| 11239 | item = sema.intAddScalar(item, try mod.intValue(operand_ty, 1), operand_ty) catch |err| switch (err) { |
| 11240 | error.Overflow => unreachable, |
| 11241 | else => |e| return e, |
| 11242 | }; |
| 11233 | 11243 | }) { |
| 11234 | 11244 | cases_len += 1; |
| 11235 | 11245 | |
| ... | ... | @@ -13363,10 +13373,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13363 | 13373 | |
| 13364 | 13374 | if (maybe_rhs_val) |rhs_val| { |
| 13365 | 13375 | if (is_int) { |
| 13366 | | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); |
| 13367 | | var vector_index: usize = undefined; |
| 13368 | | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { |
| 13369 | | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 13376 | var overflow_idx: ?usize = null; |
| 13377 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13378 | if (overflow_idx) |vec_idx| { |
| 13379 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13370 | 13380 | } |
| 13371 | 13381 | return sema.addConstant(resolved_type, res); |
| 13372 | 13382 | } else { |
| ... | ... | @@ -13490,10 +13500,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13490 | 13500 | if (!(modulus_val.compareAllWithZero(.eq, mod))) { |
| 13491 | 13501 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 13492 | 13502 | } |
| 13493 | | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); |
| 13494 | | var vector_index: usize = undefined; |
| 13495 | | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { |
| 13496 | | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 13503 | var overflow_idx: ?usize = null; |
| 13504 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13505 | if (overflow_idx) |vec_idx| { |
| 13506 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13497 | 13507 | } |
| 13498 | 13508 | return sema.addConstant(resolved_type, res); |
| 13499 | 13509 | } else { |
| ... | ... | @@ -13785,10 +13795,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13785 | 13795 | |
| 13786 | 13796 | if (maybe_rhs_val) |rhs_val| { |
| 13787 | 13797 | if (is_int) { |
| 13788 | | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); |
| 13789 | | var vector_index: usize = undefined; |
| 13790 | | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { |
| 13791 | | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 13798 | var overflow_idx: ?usize = null; |
| 13799 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13800 | if (overflow_idx) |vec_idx| { |
| 13801 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13792 | 13802 | } |
| 13793 | 13803 | return sema.addConstant(resolved_type, res); |
| 13794 | 13804 | } else { |
| ... | ... | @@ -14651,10 +14661,10 @@ fn analyzeArithmetic( |
| 14651 | 14661 | } |
| 14652 | 14662 | if (maybe_rhs_val) |rhs_val| { |
| 14653 | 14663 | if (is_int) { |
| 14654 | | const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type); |
| 14655 | | var vector_index: usize = undefined; |
| 14656 | | if (!(try sema.intFitsInType(sum, resolved_type, &vector_index))) { |
| 14657 | | return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vector_index); |
| 14664 | var overflow_idx: ?usize = null; |
| 14665 | const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type, &overflow_idx); |
| 14666 | if (overflow_idx) |vec_idx| { |
| 14667 | return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vec_idx); |
| 14658 | 14668 | } |
| 14659 | 14669 | return sema.addConstant(resolved_type, sum); |
| 14660 | 14670 | } else { |
| ... | ... | @@ -14709,7 +14719,7 @@ fn analyzeArithmetic( |
| 14709 | 14719 | } |
| 14710 | 14720 | if (maybe_lhs_val) |lhs_val| { |
| 14711 | 14721 | const val = if (scalar_tag == .ComptimeInt) |
| 14712 | | try sema.intAdd(lhs_val, rhs_val, resolved_type) |
| 14722 | try sema.intAdd(lhs_val, rhs_val, resolved_type, undefined) |
| 14713 | 14723 | else |
| 14714 | 14724 | try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod); |
| 14715 | 14725 | |
| ... | ... | @@ -14748,10 +14758,10 @@ fn analyzeArithmetic( |
| 14748 | 14758 | } |
| 14749 | 14759 | if (maybe_rhs_val) |rhs_val| { |
| 14750 | 14760 | if (is_int) { |
| 14751 | | const diff = try sema.intSub(lhs_val, rhs_val, resolved_type); |
| 14752 | | var vector_index: usize = undefined; |
| 14753 | | if (!(try sema.intFitsInType(diff, resolved_type, &vector_index))) { |
| 14754 | | return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vector_index); |
| 14761 | var overflow_idx: ?usize = null; |
| 14762 | const diff = try sema.intSub(lhs_val, rhs_val, resolved_type, &overflow_idx); |
| 14763 | if (overflow_idx) |vec_idx| { |
| 14764 | return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vec_idx); |
| 14755 | 14765 | } |
| 14756 | 14766 | return sema.addConstant(resolved_type, diff); |
| 14757 | 14767 | } else { |
| ... | ... | @@ -14806,7 +14816,7 @@ fn analyzeArithmetic( |
| 14806 | 14816 | } |
| 14807 | 14817 | if (maybe_rhs_val) |rhs_val| { |
| 14808 | 14818 | const val = if (scalar_tag == .ComptimeInt) |
| 14809 | | try sema.intSub(lhs_val, rhs_val, resolved_type) |
| 14819 | try sema.intSub(lhs_val, rhs_val, resolved_type, undefined) |
| 14810 | 14820 | else |
| 14811 | 14821 | try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod); |
| 14812 | 14822 | |
| ... | ... | @@ -14901,10 +14911,10 @@ fn analyzeArithmetic( |
| 14901 | 14911 | } |
| 14902 | 14912 | } |
| 14903 | 14913 | if (is_int) { |
| 14904 | | const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod); |
| 14905 | | var vector_index: usize = undefined; |
| 14906 | | if (!(try sema.intFitsInType(product, resolved_type, &vector_index))) { |
| 14907 | | return sema.failWithIntegerOverflow(block, src, resolved_type, product, vector_index); |
| 14914 | var overflow_idx: ?usize = null; |
| 14915 | const product = try lhs_val.intMul(rhs_val, resolved_type, &overflow_idx, sema.arena, sema.mod); |
| 14916 | if (overflow_idx) |vec_idx| { |
| 14917 | return sema.failWithIntegerOverflow(block, src, resolved_type, product, vec_idx); |
| 14908 | 14918 | } |
| 14909 | 14919 | return sema.addConstant(resolved_type, product); |
| 14910 | 14920 | } else { |
| ... | ... | @@ -15008,7 +15018,7 @@ fn analyzeArithmetic( |
| 15008 | 15018 | } |
| 15009 | 15019 | |
| 15010 | 15020 | const val = if (scalar_tag == .ComptimeInt) |
| 15011 | | try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod) |
| 15021 | try lhs_val.intMul(rhs_val, resolved_type, undefined, sema.arena, sema.mod) |
| 15012 | 15022 | else |
| 15013 | 15023 | try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, sema.mod); |
| 15014 | 15024 | |
| ... | ... | @@ -33117,7 +33127,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 33117 | 33127 | } |
| 33118 | 33128 | |
| 33119 | 33129 | if (fields_len > 0) { |
| 33120 | | const field_count_val = try mod.intValue(int_tag_ty, fields_len - 1); |
| 33130 | const field_count_val = try mod.intValue(Type.comptime_int, fields_len - 1); |
| 33121 | 33131 | if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { |
| 33122 | 33132 | const msg = msg: { |
| 33123 | 33133 | const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{}); |
| ... | ... | @@ -33217,7 +33227,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 33217 | 33227 | break :blk val; |
| 33218 | 33228 | } else blk: { |
| 33219 | 33229 | const val = if (last_tag_val) |val| |
| 33220 | | try sema.intAdd(val, Value.one_comptime_int, int_tag_ty) |
| 33230 | try sema.intAdd(val, Value.one_comptime_int, int_tag_ty, undefined) |
| 33221 | 33231 | else |
| 33222 | 33232 | try mod.intValue(int_tag_ty, 0); |
| 33223 | 33233 | last_tag_val = val; |
| ... | ... | @@ -34435,7 +34445,28 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { |
| 34435 | 34445 | try sema.types_to_resolve.put(sema.gpa, ty.toIntern(), {}); |
| 34436 | 34446 | } |
| 34437 | 34447 | |
| 34438 | | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34448 | /// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting |
| 34449 | /// overflow_idx to the vector index the overflow was at (or 0 for a scalar). |
| 34450 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value { |
| 34451 | var overflow: usize = undefined; |
| 34452 | return sema.intAddInner(lhs, rhs, ty, &overflow) catch |err| switch (err) { |
| 34453 | error.Overflow => { |
| 34454 | const is_vec = ty.isVector(sema.mod); |
| 34455 | overflow_idx.* = if (is_vec) overflow else 0; |
| 34456 | const safe_ty = if (is_vec) try sema.mod.vectorType(.{ |
| 34457 | .len = ty.vectorLen(sema.mod), |
| 34458 | .child = .comptime_int_type, |
| 34459 | }) else Type.comptime_int; |
| 34460 | return sema.intAddInner(lhs, rhs, safe_ty, undefined) catch |err1| switch (err1) { |
| 34461 | error.Overflow => unreachable, |
| 34462 | else => |e| return e, |
| 34463 | }; |
| 34464 | }, |
| 34465 | else => |e| return e, |
| 34466 | }; |
| 34467 | } |
| 34468 | |
| 34469 | fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize) !Value { |
| 34439 | 34470 | const mod = sema.mod; |
| 34440 | 34471 | if (ty.zigTypeTag(mod) == .Vector) { |
| 34441 | 34472 | const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod)); |
| ... | ... | @@ -34443,7 +34474,14 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34443 | 34474 | for (result_data, 0..) |*scalar, i| { |
| 34444 | 34475 | const lhs_elem = try lhs.elemValue(mod, i); |
| 34445 | 34476 | const rhs_elem = try rhs.elemValue(mod, i); |
| 34446 | | scalar.* = try (try sema.intAddScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod); |
| 34477 | const val = sema.intAddScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) { |
| 34478 | error.Overflow => { |
| 34479 | overflow_idx.* = i; |
| 34480 | return error.Overflow; |
| 34481 | }, |
| 34482 | else => |e| return e, |
| 34483 | }; |
| 34484 | scalar.* = try val.intern(scalar_ty, mod); |
| 34447 | 34485 | } |
| 34448 | 34486 | return (try mod.intern(.{ .aggregate = .{ |
| 34449 | 34487 | .ty = ty.toIntern(), |
| ... | ... | @@ -34455,6 +34493,11 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34455 | 34493 | |
| 34456 | 34494 | fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34457 | 34495 | const mod = sema.mod; |
| 34496 | if (scalar_ty.toIntern() != .comptime_int_type) { |
| 34497 | const res = try sema.intAddWithOverflowScalar(lhs, rhs, scalar_ty); |
| 34498 | if (res.overflow_bit.compareAllWithZero(.neq, mod)) return error.Overflow; |
| 34499 | return res.wrapped_result; |
| 34500 | } |
| 34458 | 34501 | // TODO is this a performance issue? maybe we should try the operation without |
| 34459 | 34502 | // resorting to BigInt first. |
| 34460 | 34503 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -34467,10 +34510,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34467 | 34510 | ); |
| 34468 | 34511 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 34469 | 34512 | result_bigint.add(lhs_bigint, rhs_bigint); |
| 34470 | | if (scalar_ty.toIntern() != .comptime_int_type) { |
| 34471 | | const int_info = scalar_ty.intInfo(mod); |
| 34472 | | result_bigint.truncate(result_bigint.toConst(), int_info.signedness, int_info.bits); |
| 34473 | | } |
| 34474 | 34513 | return mod.intValue_big(scalar_ty, result_bigint.toConst()); |
| 34475 | 34514 | } |
| 34476 | 34515 | |
| ... | ... | @@ -34485,7 +34524,7 @@ fn numberAddWrapScalar( |
| 34485 | 34524 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; |
| 34486 | 34525 | |
| 34487 | 34526 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| 34488 | | return sema.intAdd(lhs, rhs, ty); |
| 34527 | return sema.intAdd(lhs, rhs, ty, undefined); |
| 34489 | 34528 | } |
| 34490 | 34529 | |
| 34491 | 34530 | if (ty.isAnyFloat()) { |
| ... | ... | @@ -34496,7 +34535,28 @@ fn numberAddWrapScalar( |
| 34496 | 34535 | return overflow_result.wrapped_result; |
| 34497 | 34536 | } |
| 34498 | 34537 | |
| 34499 | | fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34538 | /// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting |
| 34539 | /// overflow_idx to the vector index the overflow was at (or 0 for a scalar). |
| 34540 | fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value { |
| 34541 | var overflow: usize = undefined; |
| 34542 | return sema.intSubInner(lhs, rhs, ty, &overflow) catch |err| switch (err) { |
| 34543 | error.Overflow => { |
| 34544 | const is_vec = ty.isVector(sema.mod); |
| 34545 | overflow_idx.* = if (is_vec) overflow else 0; |
| 34546 | const safe_ty = if (is_vec) try sema.mod.vectorType(.{ |
| 34547 | .len = ty.vectorLen(sema.mod), |
| 34548 | .child = .comptime_int_type, |
| 34549 | }) else Type.comptime_int; |
| 34550 | return sema.intSubInner(lhs, rhs, safe_ty, undefined) catch |err1| switch (err1) { |
| 34551 | error.Overflow => unreachable, |
| 34552 | else => |e| return e, |
| 34553 | }; |
| 34554 | }, |
| 34555 | else => |e| return e, |
| 34556 | }; |
| 34557 | } |
| 34558 | |
| 34559 | fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize) !Value { |
| 34500 | 34560 | const mod = sema.mod; |
| 34501 | 34561 | if (ty.zigTypeTag(mod) == .Vector) { |
| 34502 | 34562 | const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod)); |
| ... | ... | @@ -34504,7 +34564,14 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34504 | 34564 | for (result_data, 0..) |*scalar, i| { |
| 34505 | 34565 | const lhs_elem = try lhs.elemValue(sema.mod, i); |
| 34506 | 34566 | const rhs_elem = try rhs.elemValue(sema.mod, i); |
| 34507 | | scalar.* = try (try sema.intSubScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod); |
| 34567 | const val = sema.intSubScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) { |
| 34568 | error.Overflow => { |
| 34569 | overflow_idx.* = i; |
| 34570 | return error.Overflow; |
| 34571 | }, |
| 34572 | else => |e| return e, |
| 34573 | }; |
| 34574 | scalar.* = try val.intern(scalar_ty, mod); |
| 34508 | 34575 | } |
| 34509 | 34576 | return (try mod.intern(.{ .aggregate = .{ |
| 34510 | 34577 | .ty = ty.toIntern(), |
| ... | ... | @@ -34516,6 +34583,11 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34516 | 34583 | |
| 34517 | 34584 | fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34518 | 34585 | const mod = sema.mod; |
| 34586 | if (scalar_ty.toIntern() != .comptime_int_type) { |
| 34587 | const res = try sema.intSubWithOverflowScalar(lhs, rhs, scalar_ty); |
| 34588 | if (res.overflow_bit.compareAllWithZero(.neq, mod)) return error.Overflow; |
| 34589 | return res.wrapped_result; |
| 34590 | } |
| 34519 | 34591 | // TODO is this a performance issue? maybe we should try the operation without |
| 34520 | 34592 | // resorting to BigInt first. |
| 34521 | 34593 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -34542,7 +34614,7 @@ fn numberSubWrapScalar( |
| 34542 | 34614 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; |
| 34543 | 34615 | |
| 34544 | 34616 | if (ty.zigTypeTag(mod) == .ComptimeInt) { |
| 34545 | | return sema.intSub(lhs, rhs, ty); |
| 34617 | return sema.intSub(lhs, rhs, ty, undefined); |
| 34546 | 34618 | } |
| 34547 | 34619 | |
| 34548 | 34620 | if (ty.isAnyFloat()) { |