| ... | @@ -8209,25 +8209,59 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -8209,25 +8209,59 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 8209 | | 8209 | |
| 8210 | bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt; | 8210 | bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt; |
| 8211 | bool is_signed = ((resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) || | 8211 | bool is_signed = ((resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) || |
| | 8212 | resolved_type->id == TypeTableEntryIdFloat || |
| | 8213 | (resolved_type->id == TypeTableEntryIdNumLitFloat && |
| | 8214 | (op1->value.data.x_bignum.data.x_float < 0.0 || op2->value.data.x_bignum.data.x_float < 0.0)) || |
| 8212 | (resolved_type->id == TypeTableEntryIdNumLitInt && | 8215 | (resolved_type->id == TypeTableEntryIdNumLitInt && |
| 8213 | (op1->value.data.x_bignum.is_negative || op2->value.data.x_bignum.is_negative))); | 8216 | (op1->value.data.x_bignum.is_negative || op2->value.data.x_bignum.is_negative))); |
| 8214 | if (op_id == IrBinOpDivUnspecified) { | 8217 | if (op_id == IrBinOpDivUnspecified) { |
| 8215 | if (is_signed) { | 8218 | if (is_int && is_signed) { |
| 8216 | ir_add_error(ira, &bin_op_instruction->base, | 8219 | bool ok = false; |
| 8217 | buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact", | 8220 | if (instr_is_comptime(op1) && instr_is_comptime(op2)) { |
| 8218 | buf_ptr(&op1->value.type->name), | 8221 | BigNum trunc_result; |
| 8219 | buf_ptr(&op2->value.type->name))); | 8222 | BigNum floor_result; |
| 8220 | return ira->codegen->builtin_types.entry_invalid; | 8223 | if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { |
| | 8224 | zig_unreachable(); |
| | 8225 | } |
| | 8226 | if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { |
| | 8227 | zig_unreachable(); |
| | 8228 | } |
| | 8229 | if (bignum_cmp_eq(&trunc_result, &floor_result)) { |
| | 8230 | ok = true; |
| | 8231 | op_id = IrBinOpDivTrunc; |
| | 8232 | } |
| | 8233 | } |
| | 8234 | if (!ok) { |
| | 8235 | ir_add_error(ira, &bin_op_instruction->base, |
| | 8236 | buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact", |
| | 8237 | buf_ptr(&op1->value.type->name), |
| | 8238 | buf_ptr(&op2->value.type->name))); |
| | 8239 | return ira->codegen->builtin_types.entry_invalid; |
| | 8240 | } |
| 8221 | } else if (is_int) { | 8241 | } else if (is_int) { |
| 8222 | op_id = IrBinOpDivTrunc; | 8242 | op_id = IrBinOpDivTrunc; |
| 8223 | } | 8243 | } |
| 8224 | } else if (op_id == IrBinOpRemUnspecified) { | 8244 | } else if (op_id == IrBinOpRemUnspecified) { |
| 8225 | if (is_signed) { | 8245 | if (is_signed) { |
| 8226 | ir_add_error(ira, &bin_op_instruction->base, | 8246 | bool ok = false; |
| 8227 | buf_sprintf("remainder division with '%s' and '%s': signed integers must use @rem or @mod", | 8247 | if (instr_is_comptime(op1) && instr_is_comptime(op2)) { |
| 8228 | buf_ptr(&op1->value.type->name), | 8248 | BigNum rem_result; |
| 8229 | buf_ptr(&op2->value.type->name))); | 8249 | BigNum mod_result; |
| 8230 | return ira->codegen->builtin_types.entry_invalid; | 8250 | if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { |
| | 8251 | zig_unreachable(); |
| | 8252 | } |
| | 8253 | if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { |
| | 8254 | zig_unreachable(); |
| | 8255 | } |
| | 8256 | ok = bignum_cmp_eq(&rem_result, &mod_result); |
| | 8257 | } |
| | 8258 | if (!ok) { |
| | 8259 | ir_add_error(ira, &bin_op_instruction->base, |
| | 8260 | buf_sprintf("remainder division with '%s' and '%s': signed integers and floats must use @rem or @mod", |
| | 8261 | buf_ptr(&op1->value.type->name), |
| | 8262 | buf_ptr(&op2->value.type->name))); |
| | 8263 | return ira->codegen->builtin_types.entry_invalid; |
| | 8264 | } |
| 8231 | } | 8265 | } |
| 8232 | op_id = IrBinOpRemRem; | 8266 | op_id = IrBinOpRemRem; |
| 8233 | } | 8267 | } |