| ... | @@ -3125,11 +3125,11 @@ fn zirEnumDecl( | ... | @@ -3125,11 +3125,11 @@ fn zirEnumDecl( |
| 3125 | return sema.failWithOwnedErrorMsg(msg); | 3125 | return sema.failWithOwnedErrorMsg(msg); |
| 3126 | } | 3126 | } |
| 3127 | | 3127 | |
| 3128 | if (has_tag_value) { | 3128 | const tag_overflow = if (has_tag_value) overflow: { |
| 3129 | const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 3129 | const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 3130 | extra_index += 1; | 3130 | extra_index += 1; |
| 3131 | const tag_inst = try sema.resolveInst(tag_val_ref); | 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 | error.NeededSourceLocation => { | 3133 | error.NeededSourceLocation => { |
| 3134 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ | 3134 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3135 | .index = field_i, | 3135 | .index = field_i, |
| ... | @@ -3140,43 +3140,50 @@ fn zirEnumDecl( | ... | @@ -3140,43 +3140,50 @@ fn zirEnumDecl( |
| 3140 | }, | 3140 | }, |
| 3141 | else => |e| return e, | 3141 | else => |e| return e, |
| 3142 | }; | 3142 | }; |
| 3143 | last_tag_val = tag_val; | 3143 | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; |
| 3144 | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, tag_val.toIntern())) |other_index| { | 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 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ | 3146 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3146 | .index = field_i, | 3147 | .index = field_i, |
| 3147 | .range = .value, | 3148 | .range = .value, |
| 3148 | }).lazy; | 3149 | }).lazy; |
| 3149 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; | 3150 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; |
| 3150 | const msg = msg: { | 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 | errdefer msg.destroy(gpa); | 3153 | errdefer msg.destroy(gpa); |
| 3153 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); | 3154 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3154 | break :msg msg; | 3155 | break :msg msg; |
| 3155 | }; | 3156 | }; |
| 3156 | return sema.failWithOwnedErrorMsg(msg); | 3157 | return sema.failWithOwnedErrorMsg(msg); |
| 3157 | } | 3158 | } |
| 3158 | } else if (any_values) { | 3159 | break :overflow false; |
| 3159 | const tag_val = if (last_tag_val) |val| | 3160 | } else if (any_values) overflow: { |
| 3160 | try sema.intAdd(val, try mod.intValue(int_tag_ty, 1), int_tag_ty) | 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 | else | 3164 | else |
| 3162 | try mod.intValue(int_tag_ty, 0); | 3165 | try mod.intValue(int_tag_ty, 0); |
| 3163 | last_tag_val = tag_val; | 3166 | if (overflow != null) break :overflow true; |
| 3164 | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, tag_val.toIntern())) |other_index| { | 3167 | if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| { |
| 3165 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; | 3168 | const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy; |
| 3166 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; | 3169 | const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy; |
| 3167 | const msg = msg: { | 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 | errdefer msg.destroy(gpa); | 3172 | errdefer msg.destroy(gpa); |
| 3170 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); | 3173 | try sema.errNote(block, other_field_src, msg, "other occurrence here", .{}); |
| 3171 | break :msg msg; | 3174 | break :msg msg; |
| 3172 | }; | 3175 | }; |
| 3173 | return sema.failWithOwnedErrorMsg(msg); | 3176 | return sema.failWithOwnedErrorMsg(msg); |
| 3174 | } | 3177 | } |
| 3175 | } else { | 3178 | break :overflow false; |
| 3176 | last_tag_val = try mod.intValue(int_tag_ty, field_i); | 3179 | } else overflow: { |
| 3177 | } | 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 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ | 3187 | const value_src = mod.fieldSrcLoc(new_decl_index, .{ |
| 3181 | .index = field_i, | 3188 | .index = field_i, |
| 3182 | .range = if (has_tag_value) .value else .name, | 3189 | .range = if (has_tag_value) .value else .name, |
| ... | @@ -9692,7 +9699,7 @@ fn intCast( | ... | @@ -9692,7 +9699,7 @@ fn intCast( |
| 9692 | const dest_range_val = if (wanted_info.signedness == .signed) range_val: { | 9699 | const dest_range_val = if (wanted_info.signedness == .signed) range_val: { |
| 9693 | const one = try mod.intValue(unsigned_operand_ty, 1); | 9700 | const one = try mod.intValue(unsigned_operand_ty, 1); |
| 9694 | const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod); | 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 | } else try mod.getCoerced(dest_max_val, unsigned_operand_ty); | 9703 | } else try mod.getCoerced(dest_max_val, unsigned_operand_ty); |
| 9697 | const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val); | 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,7 +11236,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11229 | | 11236 | |
| 11230 | while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ | 11237 | while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({ |
| 11231 | // Previous validation has resolved any possible lazy values. | 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 | cases_len += 1; | 11244 | cases_len += 1; |
| 11235 | | 11245 | |
| ... | @@ -13363,10 +13373,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins | ... | @@ -13363,10 +13373,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 13363 | | 13373 | |
| 13364 | if (maybe_rhs_val) |rhs_val| { | 13374 | if (maybe_rhs_val) |rhs_val| { |
| 13365 | if (is_int) { | 13375 | if (is_int) { |
| 13366 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); | 13376 | var overflow_idx: ?usize = null; |
| 13367 | var vector_index: usize = undefined; | 13377 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13368 | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { | 13378 | if (overflow_idx) |vec_idx| { |
| 13369 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); | 13379 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13370 | } | 13380 | } |
| 13371 | return sema.addConstant(resolved_type, res); | 13381 | return sema.addConstant(resolved_type, res); |
| 13372 | } else { | 13382 | } else { |
| ... | @@ -13490,10 +13500,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13490,10 +13500,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13490 | if (!(modulus_val.compareAllWithZero(.eq, mod))) { | 13500 | if (!(modulus_val.compareAllWithZero(.eq, mod))) { |
| 13491 | return sema.fail(block, src, "exact division produced remainder", .{}); | 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); | 13503 | var overflow_idx: ?usize = null; |
| 13494 | var vector_index: usize = undefined; | 13504 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13495 | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { | 13505 | if (overflow_idx) |vec_idx| { |
| 13496 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); | 13506 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13497 | } | 13507 | } |
| 13498 | return sema.addConstant(resolved_type, res); | 13508 | return sema.addConstant(resolved_type, res); |
| 13499 | } else { | 13509 | } else { |
| ... | @@ -13785,10 +13795,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13785,10 +13795,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13785 | | 13795 | |
| 13786 | if (maybe_rhs_val) |rhs_val| { | 13796 | if (maybe_rhs_val) |rhs_val| { |
| 13787 | if (is_int) { | 13797 | if (is_int) { |
| 13788 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod); | 13798 | var overflow_idx: ?usize = null; |
| 13789 | var vector_index: usize = undefined; | 13799 | const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod); |
| 13790 | if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) { | 13800 | if (overflow_idx) |vec_idx| { |
| 13791 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); | 13801 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx); |
| 13792 | } | 13802 | } |
| 13793 | return sema.addConstant(resolved_type, res); | 13803 | return sema.addConstant(resolved_type, res); |
| 13794 | } else { | 13804 | } else { |
| ... | @@ -14651,10 +14661,10 @@ fn analyzeArithmetic( | ... | @@ -14651,10 +14661,10 @@ fn analyzeArithmetic( |
| 14651 | } | 14661 | } |
| 14652 | if (maybe_rhs_val) |rhs_val| { | 14662 | if (maybe_rhs_val) |rhs_val| { |
| 14653 | if (is_int) { | 14663 | if (is_int) { |
| 14654 | const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type); | 14664 | var overflow_idx: ?usize = null; |
| 14655 | var vector_index: usize = undefined; | 14665 | const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type, &overflow_idx); |
| 14656 | if (!(try sema.intFitsInType(sum, resolved_type, &vector_index))) { | 14666 | if (overflow_idx) |vec_idx| { |
| 14657 | return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vector_index); | 14667 | return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vec_idx); |
| 14658 | } | 14668 | } |
| 14659 | return sema.addConstant(resolved_type, sum); | 14669 | return sema.addConstant(resolved_type, sum); |
| 14660 | } else { | 14670 | } else { |
| ... | @@ -14709,7 +14719,7 @@ fn analyzeArithmetic( | ... | @@ -14709,7 +14719,7 @@ fn analyzeArithmetic( |
| 14709 | } | 14719 | } |
| 14710 | if (maybe_lhs_val) |lhs_val| { | 14720 | if (maybe_lhs_val) |lhs_val| { |
| 14711 | const val = if (scalar_tag == .ComptimeInt) | 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 | else | 14723 | else |
| 14714 | try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod); | 14724 | try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod); |
| 14715 | | 14725 | |
| ... | @@ -14748,10 +14758,10 @@ fn analyzeArithmetic( | ... | @@ -14748,10 +14758,10 @@ fn analyzeArithmetic( |
| 14748 | } | 14758 | } |
| 14749 | if (maybe_rhs_val) |rhs_val| { | 14759 | if (maybe_rhs_val) |rhs_val| { |
| 14750 | if (is_int) { | 14760 | if (is_int) { |
| 14751 | const diff = try sema.intSub(lhs_val, rhs_val, resolved_type); | 14761 | var overflow_idx: ?usize = null; |
| 14752 | var vector_index: usize = undefined; | 14762 | const diff = try sema.intSub(lhs_val, rhs_val, resolved_type, &overflow_idx); |
| 14753 | if (!(try sema.intFitsInType(diff, resolved_type, &vector_index))) { | 14763 | if (overflow_idx) |vec_idx| { |
| 14754 | return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vector_index); | 14764 | return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vec_idx); |
| 14755 | } | 14765 | } |
| 14756 | return sema.addConstant(resolved_type, diff); | 14766 | return sema.addConstant(resolved_type, diff); |
| 14757 | } else { | 14767 | } else { |
| ... | @@ -14806,7 +14816,7 @@ fn analyzeArithmetic( | ... | @@ -14806,7 +14816,7 @@ fn analyzeArithmetic( |
| 14806 | } | 14816 | } |
| 14807 | if (maybe_rhs_val) |rhs_val| { | 14817 | if (maybe_rhs_val) |rhs_val| { |
| 14808 | const val = if (scalar_tag == .ComptimeInt) | 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 | else | 14820 | else |
| 14811 | try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod); | 14821 | try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod); |
| 14812 | | 14822 | |
| ... | @@ -14901,10 +14911,10 @@ fn analyzeArithmetic( | ... | @@ -14901,10 +14911,10 @@ fn analyzeArithmetic( |
| 14901 | } | 14911 | } |
| 14902 | } | 14912 | } |
| 14903 | if (is_int) { | 14913 | if (is_int) { |
| 14904 | const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod); | 14914 | var overflow_idx: ?usize = null; |
| 14905 | var vector_index: usize = undefined; | 14915 | const product = try lhs_val.intMul(rhs_val, resolved_type, &overflow_idx, sema.arena, sema.mod); |
| 14906 | if (!(try sema.intFitsInType(product, resolved_type, &vector_index))) { | 14916 | if (overflow_idx) |vec_idx| { |
| 14907 | return sema.failWithIntegerOverflow(block, src, resolved_type, product, vector_index); | 14917 | return sema.failWithIntegerOverflow(block, src, resolved_type, product, vec_idx); |
| 14908 | } | 14918 | } |
| 14909 | return sema.addConstant(resolved_type, product); | 14919 | return sema.addConstant(resolved_type, product); |
| 14910 | } else { | 14920 | } else { |
| ... | @@ -15008,7 +15018,7 @@ fn analyzeArithmetic( | ... | @@ -15008,7 +15018,7 @@ fn analyzeArithmetic( |
| 15008 | } | 15018 | } |
| 15009 | | 15019 | |
| 15010 | const val = if (scalar_tag == .ComptimeInt) | 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 | else | 15022 | else |
| 15013 | try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, sema.mod); | 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,7 +33127,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 33117 | } | 33127 | } |
| 33118 | | 33128 | |
| 33119 | if (fields_len > 0) { | 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 | if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { | 33131 | if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { |
| 33122 | const msg = msg: { | 33132 | const msg = msg: { |
| 33123 | const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{}); | 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,7 +33227,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 33217 | break :blk val; | 33227 | break :blk val; |
| 33218 | } else blk: { | 33228 | } else blk: { |
| 33219 | const val = if (last_tag_val) |val| | 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 | else | 33231 | else |
| 33222 | try mod.intValue(int_tag_ty, 0); | 33232 | try mod.intValue(int_tag_ty, 0); |
| 33223 | last_tag_val = val; | 33233 | last_tag_val = val; |
| ... | @@ -34435,7 +34445,28 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { | ... | @@ -34435,7 +34445,28 @@ fn queueFullTypeResolution(sema: *Sema, ty: Type) !void { |
| 34435 | try sema.types_to_resolve.put(sema.gpa, ty.toIntern(), {}); | 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 | const mod = sema.mod; | 34470 | const mod = sema.mod; |
| 34440 | if (ty.zigTypeTag(mod) == .Vector) { | 34471 | if (ty.zigTypeTag(mod) == .Vector) { |
| 34441 | const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod)); | 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,7 +34474,14 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34443 | for (result_data, 0..) |*scalar, i| { | 34474 | for (result_data, 0..) |*scalar, i| { |
| 34444 | const lhs_elem = try lhs.elemValue(mod, i); | 34475 | const lhs_elem = try lhs.elemValue(mod, i); |
| 34445 | const rhs_elem = try rhs.elemValue(mod, i); | 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 | return (try mod.intern(.{ .aggregate = .{ | 34486 | return (try mod.intern(.{ .aggregate = .{ |
| 34449 | .ty = ty.toIntern(), | 34487 | .ty = ty.toIntern(), |
| ... | @@ -34455,6 +34493,11 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | ... | @@ -34455,6 +34493,11 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34455 | | 34493 | |
| 34456 | fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { | 34494 | fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34457 | const mod = sema.mod; | 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 | // TODO is this a performance issue? maybe we should try the operation without | 34501 | // TODO is this a performance issue? maybe we should try the operation without |
| 34459 | // resorting to BigInt first. | 34502 | // resorting to BigInt first. |
| 34460 | var lhs_space: Value.BigIntSpace = undefined; | 34503 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | @@ -34467,10 +34510,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { | ... | @@ -34467,10 +34510,6 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34467 | ); | 34510 | ); |
| 34468 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 34511 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 34469 | result_bigint.add(lhs_bigint, rhs_bigint); | 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 | return mod.intValue_big(scalar_ty, result_bigint.toConst()); | 34513 | return mod.intValue_big(scalar_ty, result_bigint.toConst()); |
| 34475 | } | 34514 | } |
| 34476 | | 34515 | |
| ... | @@ -34485,7 +34524,7 @@ fn numberAddWrapScalar( | ... | @@ -34485,7 +34524,7 @@ fn numberAddWrapScalar( |
| 34485 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; | 34524 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; |
| 34486 | | 34525 | |
| 34487 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | 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 | if (ty.isAnyFloat()) { | 34530 | if (ty.isAnyFloat()) { |
| ... | @@ -34496,7 +34535,28 @@ fn numberAddWrapScalar( | ... | @@ -34496,7 +34535,28 @@ fn numberAddWrapScalar( |
| 34496 | return overflow_result.wrapped_result; | 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 | const mod = sema.mod; | 34560 | const mod = sema.mod; |
| 34501 | if (ty.zigTypeTag(mod) == .Vector) { | 34561 | if (ty.zigTypeTag(mod) == .Vector) { |
| 34502 | const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod)); | 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,7 +34564,14 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34504 | for (result_data, 0..) |*scalar, i| { | 34564 | for (result_data, 0..) |*scalar, i| { |
| 34505 | const lhs_elem = try lhs.elemValue(sema.mod, i); | 34565 | const lhs_elem = try lhs.elemValue(sema.mod, i); |
| 34506 | const rhs_elem = try rhs.elemValue(sema.mod, i); | 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 | return (try mod.intern(.{ .aggregate = .{ | 34576 | return (try mod.intern(.{ .aggregate = .{ |
| 34510 | .ty = ty.toIntern(), | 34577 | .ty = ty.toIntern(), |
| ... | @@ -34516,6 +34583,11 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | ... | @@ -34516,6 +34583,11 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 34516 | | 34583 | |
| 34517 | fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { | 34584 | fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value { |
| 34518 | const mod = sema.mod; | 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 | // TODO is this a performance issue? maybe we should try the operation without | 34591 | // TODO is this a performance issue? maybe we should try the operation without |
| 34520 | // resorting to BigInt first. | 34592 | // resorting to BigInt first. |
| 34521 | var lhs_space: Value.BigIntSpace = undefined; | 34593 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | @@ -34542,7 +34614,7 @@ fn numberSubWrapScalar( | ... | @@ -34542,7 +34614,7 @@ fn numberSubWrapScalar( |
| 34542 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; | 34614 | if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; |
| 34543 | | 34615 | |
| 34544 | if (ty.zigTypeTag(mod) == .ComptimeInt) { | 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 | if (ty.isAnyFloat()) { | 34620 | if (ty.isAnyFloat()) { |