| ... | ... | @@ -1792,6 +1792,24 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *sou |
| 1792 | 1792 | return &bin_op_instruction->base; |
| 1793 | 1793 | } |
| 1794 | 1794 | |
| 1795 | static IrInstruction *ir_build_bin_op_gen(IrAnalyze *ira, IrInstruction *source_instr, ZigType *res_type, |
| 1796 | IrBinOp op_id, IrInstruction *op1, IrInstruction *op2, bool safety_check_on) |
| 1797 | { |
| 1798 | IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(&ira->new_irb, |
| 1799 | source_instr->scope, source_instr->source_node); |
| 1800 | bin_op_instruction->base.value->type = res_type; |
| 1801 | bin_op_instruction->op_id = op_id; |
| 1802 | bin_op_instruction->op1 = op1; |
| 1803 | bin_op_instruction->op2 = op2; |
| 1804 | bin_op_instruction->safety_check_on = safety_check_on; |
| 1805 | |
| 1806 | ir_ref_instruction(op1, ira->new_irb.current_basic_block); |
| 1807 | ir_ref_instruction(op2, ira->new_irb.current_basic_block); |
| 1808 | |
| 1809 | return &bin_op_instruction->base; |
| 1810 | } |
| 1811 | |
| 1812 | |
| 1795 | 1813 | static IrInstruction *ir_build_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1796 | 1814 | IrInstruction *op1, IrInstruction *op2, Buf *type_name) |
| 1797 | 1815 | { |
| ... | ... | @@ -9591,51 +9609,58 @@ static bool float_is_nan(ZigValue *op) { |
| 9591 | 9609 | } |
| 9592 | 9610 | |
| 9593 | 9611 | static Cmp float_cmp(ZigValue *op1, ZigValue *op2) { |
| 9594 | | assert(op1->type == op2->type); |
| 9595 | | if (op1->type->id == ZigTypeIdComptimeFloat) { |
| 9596 | | return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 9597 | | } else if (op1->type->id == ZigTypeIdFloat) { |
| 9598 | | switch (op1->type->data.floating.bit_count) { |
| 9599 | | case 16: |
| 9600 | | if (f16_lt(op1->data.x_f16, op2->data.x_f16)) { |
| 9601 | | return CmpLT; |
| 9602 | | } else if (f16_lt(op2->data.x_f16, op1->data.x_f16)) { |
| 9603 | | return CmpGT; |
| 9604 | | } else { |
| 9605 | | return CmpEQ; |
| 9606 | | } |
| 9607 | | case 32: |
| 9608 | | if (op1->data.x_f32 > op2->data.x_f32) { |
| 9609 | | return CmpGT; |
| 9610 | | } else if (op1->data.x_f32 < op2->data.x_f32) { |
| 9611 | | return CmpLT; |
| 9612 | | } else { |
| 9613 | | return CmpEQ; |
| 9614 | | } |
| 9615 | | case 64: |
| 9616 | | if (op1->data.x_f64 > op2->data.x_f64) { |
| 9617 | | return CmpGT; |
| 9618 | | } else if (op1->data.x_f64 < op2->data.x_f64) { |
| 9619 | | return CmpLT; |
| 9620 | | } else { |
| 9621 | | return CmpEQ; |
| 9622 | | } |
| 9623 | | case 128: |
| 9624 | | if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) { |
| 9625 | | return CmpLT; |
| 9626 | | } else if (f128M_eq(&op1->data.x_f128, &op2->data.x_f128)) { |
| 9627 | | return CmpEQ; |
| 9628 | | } else { |
| 9629 | | return CmpGT; |
| 9630 | | } |
| 9631 | | default: |
| 9632 | | zig_unreachable(); |
| 9612 | if (op1->type == op2->type) { |
| 9613 | if (op1->type->id == ZigTypeIdComptimeFloat) { |
| 9614 | return bigfloat_cmp(&op1->data.x_bigfloat, &op2->data.x_bigfloat); |
| 9615 | } else if (op1->type->id == ZigTypeIdFloat) { |
| 9616 | switch (op1->type->data.floating.bit_count) { |
| 9617 | case 16: |
| 9618 | if (f16_lt(op1->data.x_f16, op2->data.x_f16)) { |
| 9619 | return CmpLT; |
| 9620 | } else if (f16_lt(op2->data.x_f16, op1->data.x_f16)) { |
| 9621 | return CmpGT; |
| 9622 | } else { |
| 9623 | return CmpEQ; |
| 9624 | } |
| 9625 | case 32: |
| 9626 | if (op1->data.x_f32 > op2->data.x_f32) { |
| 9627 | return CmpGT; |
| 9628 | } else if (op1->data.x_f32 < op2->data.x_f32) { |
| 9629 | return CmpLT; |
| 9630 | } else { |
| 9631 | return CmpEQ; |
| 9632 | } |
| 9633 | case 64: |
| 9634 | if (op1->data.x_f64 > op2->data.x_f64) { |
| 9635 | return CmpGT; |
| 9636 | } else if (op1->data.x_f64 < op2->data.x_f64) { |
| 9637 | return CmpLT; |
| 9638 | } else { |
| 9639 | return CmpEQ; |
| 9640 | } |
| 9641 | case 128: |
| 9642 | if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) { |
| 9643 | return CmpLT; |
| 9644 | } else if (f128M_eq(&op1->data.x_f128, &op2->data.x_f128)) { |
| 9645 | return CmpEQ; |
| 9646 | } else { |
| 9647 | return CmpGT; |
| 9648 | } |
| 9649 | default: |
| 9650 | zig_unreachable(); |
| 9651 | } |
| 9652 | } else { |
| 9653 | zig_unreachable(); |
| 9633 | 9654 | } |
| 9634 | | } else { |
| 9635 | | zig_unreachable(); |
| 9636 | 9655 | } |
| 9656 | BigFloat op1_big; |
| 9657 | BigFloat op2_big; |
| 9658 | float_init_bigfloat(op1, &op1_big); |
| 9659 | float_init_bigfloat(op2, &op2_big); |
| 9660 | return bigfloat_cmp(&op1_big, &op2_big); |
| 9637 | 9661 | } |
| 9638 | 9662 | |
| 9663 | // This function cannot handle NaN |
| 9639 | 9664 | static Cmp float_cmp_zero(ZigValue *op) { |
| 9640 | 9665 | if (op->type->id == ZigTypeIdComptimeFloat) { |
| 9641 | 9666 | return bigfloat_cmp_zero(&op->data.x_bigfloat); |
| ... | ... | @@ -14421,18 +14446,7 @@ static IrInstruction *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_t |
| 14421 | 14446 | if (op1_val->special == ConstValSpecialUndef || |
| 14422 | 14447 | op2_val->special == ConstValSpecialUndef) |
| 14423 | 14448 | return ir_const_undef(ira, &bin_op_instruction->base, resolved_type); |
| 14424 | | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { |
| 14425 | | if (float_is_nan(op1_val) || float_is_nan(op2_val)) { |
| 14426 | | return ir_const_bool(ira, &bin_op_instruction->base, op_id == IrBinOpCmpNotEq); |
| 14427 | | } |
| 14428 | | Cmp cmp_result = float_cmp(op1_val, op2_val); |
| 14429 | | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 14430 | | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 14431 | | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { |
| 14432 | | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 14433 | | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 14434 | | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 14435 | | } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { |
| 14449 | if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { |
| 14436 | 14450 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| 14437 | 14451 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && |
| 14438 | 14452 | (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| ... | ... | @@ -14482,6 +14496,12 @@ static Error lazy_cmp_zero(AstNode *source_node, ZigValue *val, Cmp *result) { |
| 14482 | 14496 | case ZigTypeIdInt: |
| 14483 | 14497 | *result = bigint_cmp_zero(&val->data.x_bigint); |
| 14484 | 14498 | return ErrorNone; |
| 14499 | case ZigTypeIdComptimeFloat: |
| 14500 | case ZigTypeIdFloat: |
| 14501 | if (float_is_nan(val)) |
| 14502 | return ErrorNotLazy; |
| 14503 | *result = float_cmp_zero(val); |
| 14504 | return ErrorNone; |
| 14485 | 14505 | default: |
| 14486 | 14506 | return ErrorNotLazy; |
| 14487 | 14507 | } |
| ... | ... | @@ -14511,9 +14531,450 @@ static Error lazy_cmp_zero(AstNode *source_node, ZigValue *val, Cmp *result) { |
| 14511 | 14531 | zig_unreachable(); |
| 14512 | 14532 | } |
| 14513 | 14533 | |
| 14514 | | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 14534 | static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, IrInstruction *source_instr, |
| 14535 | ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val, ZigValue *out_val) |
| 14536 | { |
| 14515 | 14537 | Error err; |
| 14538 | { |
| 14539 | // Before resolving the values, we special case comparisons against zero. These can often |
| 14540 | // be done without resolving lazy values, preventing potential dependency loops. |
| 14541 | Cmp op1_cmp_zero; |
| 14542 | if ((err = lazy_cmp_zero(source_instr->source_node, op1_val, &op1_cmp_zero))) { |
| 14543 | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 14544 | return ira->codegen->trace_err; |
| 14545 | } |
| 14546 | Cmp op2_cmp_zero; |
| 14547 | if ((err = lazy_cmp_zero(source_instr->source_node, op2_val, &op2_cmp_zero))) { |
| 14548 | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 14549 | return ira->codegen->trace_err; |
| 14550 | } |
| 14551 | bool can_cmp_zero = false; |
| 14552 | Cmp cmp_result; |
| 14553 | if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpEQ) { |
| 14554 | can_cmp_zero = true; |
| 14555 | cmp_result = CmpEQ; |
| 14556 | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpEQ) { |
| 14557 | can_cmp_zero = true; |
| 14558 | cmp_result = CmpGT; |
| 14559 | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpGT) { |
| 14560 | can_cmp_zero = true; |
| 14561 | cmp_result = CmpLT; |
| 14562 | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpEQ) { |
| 14563 | can_cmp_zero = true; |
| 14564 | cmp_result = CmpLT; |
| 14565 | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpLT) { |
| 14566 | can_cmp_zero = true; |
| 14567 | cmp_result = CmpGT; |
| 14568 | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpGT) { |
| 14569 | can_cmp_zero = true; |
| 14570 | cmp_result = CmpLT; |
| 14571 | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpLT) { |
| 14572 | can_cmp_zero = true; |
| 14573 | cmp_result = CmpGT; |
| 14574 | } |
| 14575 | if (can_cmp_zero) { |
| 14576 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 14577 | out_val->special = ConstValSpecialStatic; |
| 14578 | out_val->data.x_bool = answer; |
| 14579 | return nullptr; |
| 14580 | } |
| 14581 | } |
| 14582 | never_mind_just_calculate_it_normally: |
| 14583 | |
| 14584 | if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_instr->source_node, |
| 14585 | op1_val, UndefOk))) |
| 14586 | { |
| 14587 | return ira->codegen->trace_err; |
| 14588 | } |
| 14589 | if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_instr->source_node, |
| 14590 | op2_val, UndefOk))) |
| 14591 | { |
| 14592 | return ira->codegen->trace_err; |
| 14593 | } |
| 14594 | |
| 14595 | |
| 14596 | if (op1_val->special == ConstValSpecialUndef || op2_val->special == ConstValSpecialUndef) { |
| 14597 | out_val->special = ConstValSpecialUndef; |
| 14598 | return nullptr; |
| 14599 | } |
| 14600 | |
| 14601 | bool op1_is_float = op1_val->type->id == ZigTypeIdFloat || op1_val->type->id == ZigTypeIdComptimeFloat; |
| 14602 | bool op2_is_float = op2_val->type->id == ZigTypeIdFloat || op2_val->type->id == ZigTypeIdComptimeFloat; |
| 14603 | if (op1_is_float && op2_is_float) { |
| 14604 | if (float_is_nan(op1_val) || float_is_nan(op2_val)) { |
| 14605 | out_val->special = ConstValSpecialStatic; |
| 14606 | out_val->data.x_bool = op_id == IrBinOpCmpNotEq; |
| 14607 | return nullptr; |
| 14608 | } |
| 14609 | if (op1_val->type->id == ZigTypeIdComptimeFloat) { |
| 14610 | IrInstruction *tmp = ir_const_noval(ira, source_instr); |
| 14611 | tmp->value = op1_val; |
| 14612 | IrInstruction *casted = ir_implicit_cast(ira, tmp, op2_val->type); |
| 14613 | op1_val = casted->value; |
| 14614 | } else if (op2_val->type->id == ZigTypeIdComptimeFloat) { |
| 14615 | IrInstruction *tmp = ir_const_noval(ira, source_instr); |
| 14616 | tmp->value = op2_val; |
| 14617 | IrInstruction *casted = ir_implicit_cast(ira, tmp, op1_val->type); |
| 14618 | op2_val = casted->value; |
| 14619 | } |
| 14620 | Cmp cmp_result = float_cmp(op1_val, op2_val); |
| 14621 | out_val->special = ConstValSpecialStatic; |
| 14622 | out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result); |
| 14623 | return nullptr; |
| 14624 | } |
| 14625 | |
| 14626 | bool op1_is_int = op1_val->type->id == ZigTypeIdInt || op1_val->type->id == ZigTypeIdComptimeInt; |
| 14627 | bool op2_is_int = op2_val->type->id == ZigTypeIdInt || op2_val->type->id == ZigTypeIdComptimeInt; |
| 14628 | |
| 14629 | BigInt *op1_bigint; |
| 14630 | BigInt *op2_bigint; |
| 14631 | bool need_to_free_op1_bigint = false; |
| 14632 | bool need_to_free_op2_bigint = false; |
| 14633 | if (op1_is_float) { |
| 14634 | op1_bigint = allocate<BigInt>(1, "BigInt"); |
| 14635 | need_to_free_op1_bigint = true; |
| 14636 | float_init_bigint(op1_bigint, op1_val); |
| 14637 | } else { |
| 14638 | assert(op1_is_int); |
| 14639 | op1_bigint = &op1_val->data.x_bigint; |
| 14640 | } |
| 14641 | if (op2_is_float) { |
| 14642 | op2_bigint = allocate<BigInt>(1, "BigInt"); |
| 14643 | need_to_free_op2_bigint = true; |
| 14644 | float_init_bigint(op2_bigint, op2_val); |
| 14645 | } else { |
| 14646 | assert(op2_is_int); |
| 14647 | op2_bigint = &op2_val->data.x_bigint; |
| 14648 | } |
| 14649 | |
| 14650 | Cmp cmp_result = bigint_cmp(op1_bigint, op2_bigint); |
| 14651 | out_val->special = ConstValSpecialStatic; |
| 14652 | out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result); |
| 14516 | 14653 | |
| 14654 | if (need_to_free_op1_bigint) destroy(op1_bigint, "BigInt"); |
| 14655 | if (need_to_free_op2_bigint) destroy(op2_bigint, "BigInt"); |
| 14656 | return nullptr; |
| 14657 | } |
| 14658 | |
| 14659 | static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstruction *source_instr, |
| 14660 | IrInstruction *op1, IrInstruction *op2, IrBinOp op_id) |
| 14661 | { |
| 14662 | Error err; |
| 14663 | |
| 14664 | ZigType *scalar_result_type = ira->codegen->builtin_types.entry_bool; |
| 14665 | ZigType *result_type = scalar_result_type; |
| 14666 | ZigType *op1_scalar_type = op1->value->type; |
| 14667 | ZigType *op2_scalar_type = op2->value->type; |
| 14668 | if (op1->value->type->id == ZigTypeIdVector && op2->value->type->id == ZigTypeIdVector) { |
| 14669 | if (op1->value->type->data.vector.len != op2->value->type->data.vector.len) { |
| 14670 | ir_add_error(ira, source_instr, |
| 14671 | buf_sprintf("vector length mismatch: %" PRIu32 " and %" PRIu32, |
| 14672 | op1->value->type->data.vector.len, op2->value->type->data.vector.len)); |
| 14673 | return ira->codegen->invalid_instruction; |
| 14674 | } |
| 14675 | result_type = get_vector_type(ira->codegen, op1->value->type->data.vector.len, scalar_result_type); |
| 14676 | op1_scalar_type = op1->value->type->data.vector.elem_type; |
| 14677 | op2_scalar_type = op2->value->type->data.vector.elem_type; |
| 14678 | } else if (op1->value->type->id == ZigTypeIdVector || op2->value->type->id == ZigTypeIdVector) { |
| 14679 | ir_add_error(ira, source_instr, |
| 14680 | buf_sprintf("mixed scalar and vector operands to comparison operator: '%s' and '%s'", |
| 14681 | buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); |
| 14682 | return ira->codegen->invalid_instruction; |
| 14683 | } |
| 14684 | |
| 14685 | bool opv_op1; |
| 14686 | switch (type_has_one_possible_value(ira->codegen, op1->value->type)) { |
| 14687 | case OnePossibleValueInvalid: |
| 14688 | return ira->codegen->invalid_instruction; |
| 14689 | case OnePossibleValueYes: |
| 14690 | opv_op1 = true; |
| 14691 | break; |
| 14692 | case OnePossibleValueNo: |
| 14693 | opv_op1 = false; |
| 14694 | break; |
| 14695 | } |
| 14696 | bool opv_op2; |
| 14697 | switch (type_has_one_possible_value(ira->codegen, op2->value->type)) { |
| 14698 | case OnePossibleValueInvalid: |
| 14699 | return ira->codegen->invalid_instruction; |
| 14700 | case OnePossibleValueYes: |
| 14701 | opv_op2 = true; |
| 14702 | break; |
| 14703 | case OnePossibleValueNo: |
| 14704 | opv_op2 = false; |
| 14705 | break; |
| 14706 | } |
| 14707 | Cmp op1_cmp_zero; |
| 14708 | bool have_op1_cmp_zero = false; |
| 14709 | if ((err = lazy_cmp_zero(source_instr->source_node, op1->value, &op1_cmp_zero))) { |
| 14710 | if (err != ErrorNotLazy) return ira->codegen->invalid_instruction; |
| 14711 | } else { |
| 14712 | have_op1_cmp_zero = true; |
| 14713 | } |
| 14714 | Cmp op2_cmp_zero; |
| 14715 | bool have_op2_cmp_zero = false; |
| 14716 | if ((err = lazy_cmp_zero(source_instr->source_node, op2->value, &op2_cmp_zero))) { |
| 14717 | if (err != ErrorNotLazy) return ira->codegen->invalid_instruction; |
| 14718 | } else { |
| 14719 | have_op2_cmp_zero = true; |
| 14720 | } |
| 14721 | if (((opv_op1 || instr_is_comptime(op1)) && (opv_op2 || instr_is_comptime(op2))) || |
| 14722 | (have_op1_cmp_zero && have_op2_cmp_zero)) |
| 14723 | { |
| 14724 | IrInstruction *result_instruction = ir_const(ira, source_instr, result_type); |
| 14725 | ZigValue *out_val = result_instruction->value; |
| 14726 | if (result_type->id == ZigTypeIdVector) { |
| 14727 | size_t len = result_type->data.vector.len; |
| 14728 | expand_undef_array(ira->codegen, op1->value); |
| 14729 | expand_undef_array(ira->codegen, op2->value); |
| 14730 | out_val->special = ConstValSpecialUndef; |
| 14731 | expand_undef_array(ira->codegen, out_val); |
| 14732 | for (size_t i = 0; i < len; i += 1) { |
| 14733 | ZigValue *scalar_op1_val = &op1->value->data.x_array.data.s_none.elements[i]; |
| 14734 | ZigValue *scalar_op2_val = &op2->value->data.x_array.data.s_none.elements[i]; |
| 14735 | ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; |
| 14736 | assert(scalar_out_val->type == scalar_result_type); |
| 14737 | ErrorMsg *msg = ir_eval_bin_op_cmp_scalar(ira, source_instr, |
| 14738 | scalar_op1_val, op_id, scalar_op2_val, scalar_out_val); |
| 14739 | if (msg != nullptr) { |
| 14740 | add_error_note(ira->codegen, msg, source_instr->source_node, |
| 14741 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); |
| 14742 | return ira->codegen->invalid_instruction; |
| 14743 | } |
| 14744 | } |
| 14745 | out_val->type = result_type; |
| 14746 | out_val->special = ConstValSpecialStatic; |
| 14747 | } else { |
| 14748 | if (ir_eval_bin_op_cmp_scalar(ira, source_instr, op1->value, op_id, |
| 14749 | op2->value, out_val) != nullptr) |
| 14750 | { |
| 14751 | return ira->codegen->invalid_instruction; |
| 14752 | } |
| 14753 | } |
| 14754 | return result_instruction; |
| 14755 | } |
| 14756 | |
| 14757 | // If one operand has a comptime-known comparison with 0, and the other operand is unsigned, we might |
| 14758 | // know the answer, depending on the operator. |
| 14759 | // TODO make this work with vectors |
| 14760 | if (have_op1_cmp_zero && op2_scalar_type->id == ZigTypeIdInt && !op2_scalar_type->data.integral.is_signed) { |
| 14761 | if (op1_cmp_zero == CmpEQ) { |
| 14762 | // 0 <= unsigned_x // true |
| 14763 | // 0 > unsigned_x // false |
| 14764 | switch (op_id) { |
| 14765 | case IrBinOpCmpLessOrEq: |
| 14766 | return ir_const_bool(ira, source_instr, true); |
| 14767 | case IrBinOpCmpGreaterThan: |
| 14768 | return ir_const_bool(ira, source_instr, false); |
| 14769 | default: |
| 14770 | break; |
| 14771 | } |
| 14772 | } else if (op1_cmp_zero == CmpLT) { |
| 14773 | // -1 != unsigned_x // true |
| 14774 | // -1 <= unsigned_x // true |
| 14775 | // -1 < unsigned_x // true |
| 14776 | // -1 == unsigned_x // false |
| 14777 | // -1 >= unsigned_x // false |
| 14778 | // -1 > unsigned_x // false |
| 14779 | switch (op_id) { |
| 14780 | case IrBinOpCmpNotEq: |
| 14781 | case IrBinOpCmpLessOrEq: |
| 14782 | case IrBinOpCmpLessThan: |
| 14783 | return ir_const_bool(ira, source_instr, true); |
| 14784 | case IrBinOpCmpEq: |
| 14785 | case IrBinOpCmpGreaterOrEq: |
| 14786 | case IrBinOpCmpGreaterThan: |
| 14787 | return ir_const_bool(ira, source_instr, false); |
| 14788 | default: |
| 14789 | break; |
| 14790 | } |
| 14791 | } |
| 14792 | } |
| 14793 | if (have_op2_cmp_zero && op1_scalar_type->id == ZigTypeIdInt && !op1_scalar_type->data.integral.is_signed) { |
| 14794 | if (op2_cmp_zero == CmpEQ) { |
| 14795 | // unsigned_x < 0 // false |
| 14796 | // unsigned_x >= 0 // true |
| 14797 | switch (op_id) { |
| 14798 | case IrBinOpCmpLessThan: |
| 14799 | return ir_const_bool(ira, source_instr, false); |
| 14800 | case IrBinOpCmpGreaterOrEq: |
| 14801 | return ir_const_bool(ira, source_instr, true); |
| 14802 | default: |
| 14803 | break; |
| 14804 | } |
| 14805 | } else if (op2_cmp_zero == CmpLT) { |
| 14806 | // unsigned_x != -1 // true |
| 14807 | // unsigned_x >= -1 // true |
| 14808 | // unsigned_x > -1 // true |
| 14809 | // unsigned_x == -1 // false |
| 14810 | // unsigned_x < -1 // false |
| 14811 | // unsigned_x <= -1 // false |
| 14812 | switch (op_id) { |
| 14813 | case IrBinOpCmpNotEq: |
| 14814 | case IrBinOpCmpGreaterOrEq: |
| 14815 | case IrBinOpCmpGreaterThan: |
| 14816 | return ir_const_bool(ira, source_instr, true); |
| 14817 | case IrBinOpCmpEq: |
| 14818 | case IrBinOpCmpLessThan: |
| 14819 | case IrBinOpCmpLessOrEq: |
| 14820 | return ir_const_bool(ira, source_instr, false); |
| 14821 | default: |
| 14822 | break; |
| 14823 | } |
| 14824 | } |
| 14825 | } |
| 14826 | |
| 14827 | // It must be a runtime comparison. |
| 14828 | // For floats, emit a float comparison instruction. |
| 14829 | bool op1_is_float = op1_scalar_type->id == ZigTypeIdFloat || op1_scalar_type->id == ZigTypeIdComptimeFloat; |
| 14830 | bool op2_is_float = op2_scalar_type->id == ZigTypeIdFloat || op2_scalar_type->id == ZigTypeIdComptimeFloat; |
| 14831 | if (op1_is_float && op2_is_float) { |
| 14832 | // Implicit cast the smaller one to the larger one. |
| 14833 | ZigType *dest_scalar_type; |
| 14834 | if (op1_scalar_type->id == ZigTypeIdComptimeFloat) { |
| 14835 | dest_scalar_type = op2_scalar_type; |
| 14836 | } else if (op2_scalar_type->id == ZigTypeIdComptimeFloat) { |
| 14837 | dest_scalar_type = op1_scalar_type; |
| 14838 | } else if (op1_scalar_type->data.floating.bit_count >= op2_scalar_type->data.floating.bit_count) { |
| 14839 | dest_scalar_type = op1_scalar_type; |
| 14840 | } else { |
| 14841 | dest_scalar_type = op2_scalar_type; |
| 14842 | } |
| 14843 | ZigType *dest_type = (result_type->id == ZigTypeIdVector) ? |
| 14844 | get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type; |
| 14845 | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); |
| 14846 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, dest_type); |
| 14847 | if (type_is_invalid(casted_op1->value->type) || type_is_invalid(casted_op2->value->type)) |
| 14848 | return ira->codegen->invalid_instruction; |
| 14849 | return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); |
| 14850 | } |
| 14851 | |
| 14852 | // For mixed unsigned integer sizes, implicit cast both operands to the larger integer. |
| 14853 | // For mixed signed and unsigned integers, implicit cast both operands to a signed |
| 14854 | // integer with + 1 bit. |
| 14855 | // For mixed floats and integers, extract the integer part from the float, cast that to |
| 14856 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, |
| 14857 | // add/subtract 1. |
| 14858 | bool dest_int_is_signed = false; |
| 14859 | if (have_op1_cmp_zero) { |
| 14860 | if (op1_cmp_zero == CmpLT) dest_int_is_signed = true; |
| 14861 | } else if (op1_is_float) { |
| 14862 | dest_int_is_signed = true; |
| 14863 | } else if (op1_scalar_type->id == ZigTypeIdInt && op1_scalar_type->data.integral.is_signed) { |
| 14864 | dest_int_is_signed = true; |
| 14865 | } |
| 14866 | if (have_op2_cmp_zero) { |
| 14867 | if (op2_cmp_zero == CmpLT) dest_int_is_signed = true; |
| 14868 | } else if (op2_is_float) { |
| 14869 | dest_int_is_signed = true; |
| 14870 | } else if (op2->value->type->id == ZigTypeIdInt && op2->value->type->data.integral.is_signed) { |
| 14871 | dest_int_is_signed = true; |
| 14872 | } |
| 14873 | ZigType *dest_float_type = nullptr; |
| 14874 | uint32_t op1_bits; |
| 14875 | if (instr_is_comptime(op1)) { |
| 14876 | ZigValue *op1_val = ir_resolve_const(ira, op1, UndefOk); |
| 14877 | if (op1_val == nullptr) |
| 14878 | return ira->codegen->invalid_instruction; |
| 14879 | if (op1_val->special == ConstValSpecialUndef) |
| 14880 | return ir_const_undef(ira, source_instr, ira->codegen->builtin_types.entry_bool); |
| 14881 | if (result_type->id == ZigTypeIdVector) { |
| 14882 | ir_add_error(ira, op1, buf_sprintf("compiler bug: TODO: support comptime vector here")); |
| 14883 | return ira->codegen->invalid_instruction; |
| 14884 | } |
| 14885 | bool is_unsigned; |
| 14886 | if (op1_is_float) { |
| 14887 | BigInt bigint = {}; |
| 14888 | float_init_bigint(&bigint, op1_val); |
| 14889 | Cmp zcmp = float_cmp_zero(op1_val); |
| 14890 | if (float_has_fraction(op1_val)) { |
| 14891 | if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) { |
| 14892 | return ir_const_bool(ira, source_instr, op_id == IrBinOpCmpNotEq); |
| 14893 | } |
| 14894 | if (zcmp == CmpLT) { |
| 14895 | bigint_decr(&bigint); |
| 14896 | } else { |
| 14897 | bigint_incr(&bigint); |
| 14898 | } |
| 14899 | } |
| 14900 | op1_bits = bigint_bits_needed(&bigint); |
| 14901 | is_unsigned = zcmp != CmpLT; |
| 14902 | } else { |
| 14903 | op1_bits = bigint_bits_needed(&op1_val->data.x_bigint); |
| 14904 | is_unsigned = bigint_cmp_zero(&op1_val->data.x_bigint) != CmpLT; |
| 14905 | } |
| 14906 | if (is_unsigned && dest_int_is_signed) { |
| 14907 | op1_bits += 1; |
| 14908 | } |
| 14909 | } else if (op1_is_float) { |
| 14910 | dest_float_type = op1_scalar_type; |
| 14911 | } else { |
| 14912 | ir_assert(op1_scalar_type->id == ZigTypeIdInt, source_instr); |
| 14913 | op1_bits = op1_scalar_type->data.integral.bit_count; |
| 14914 | if (!op1_scalar_type->data.integral.is_signed && dest_int_is_signed) { |
| 14915 | op1_bits += 1; |
| 14916 | } |
| 14917 | } |
| 14918 | uint32_t op2_bits; |
| 14919 | if (instr_is_comptime(op2)) { |
| 14920 | ZigValue *op2_val = ir_resolve_const(ira, op2, UndefOk); |
| 14921 | if (op2_val == nullptr) |
| 14922 | return ira->codegen->invalid_instruction; |
| 14923 | if (op2_val->special == ConstValSpecialUndef) |
| 14924 | return ir_const_undef(ira, source_instr, ira->codegen->builtin_types.entry_bool); |
| 14925 | if (result_type->id == ZigTypeIdVector) { |
| 14926 | ir_add_error(ira, op2, buf_sprintf("compiler bug: TODO: support comptime vector here")); |
| 14927 | return ira->codegen->invalid_instruction; |
| 14928 | } |
| 14929 | bool is_unsigned; |
| 14930 | if (op2_is_float) { |
| 14931 | BigInt bigint = {}; |
| 14932 | float_init_bigint(&bigint, op2_val); |
| 14933 | Cmp zcmp = float_cmp_zero(op2_val); |
| 14934 | if (float_has_fraction(op2_val)) { |
| 14935 | if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) { |
| 14936 | return ir_const_bool(ira, source_instr, op_id == IrBinOpCmpNotEq); |
| 14937 | } |
| 14938 | if (zcmp == CmpLT) { |
| 14939 | bigint_decr(&bigint); |
| 14940 | } else { |
| 14941 | bigint_incr(&bigint); |
| 14942 | } |
| 14943 | } |
| 14944 | op2_bits = bigint_bits_needed(&bigint); |
| 14945 | is_unsigned = zcmp != CmpLT; |
| 14946 | } else { |
| 14947 | op2_bits = bigint_bits_needed(&op2_val->data.x_bigint); |
| 14948 | is_unsigned = bigint_cmp_zero(&op2_val->data.x_bigint) != CmpLT; |
| 14949 | } |
| 14950 | if (is_unsigned && dest_int_is_signed) { |
| 14951 | op2_bits += 1; |
| 14952 | } |
| 14953 | } else if (op2_is_float) { |
| 14954 | dest_float_type = op2_scalar_type; |
| 14955 | } else { |
| 14956 | ir_assert(op2_scalar_type->id == ZigTypeIdInt, source_instr); |
| 14957 | op2_bits = op2_scalar_type->data.integral.bit_count; |
| 14958 | if (!op2_scalar_type->data.integral.is_signed && dest_int_is_signed) { |
| 14959 | op2_bits += 1; |
| 14960 | } |
| 14961 | } |
| 14962 | uint32_t dest_int_bits = (op1_bits > op2_bits) ? op1_bits : op2_bits; |
| 14963 | ZigType *dest_scalar_type = (dest_float_type == nullptr) ? |
| 14964 | get_int_type(ira->codegen, dest_int_is_signed, dest_int_bits) : dest_float_type; |
| 14965 | ZigType *dest_type = (result_type->id == ZigTypeIdVector) ? |
| 14966 | get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type; |
| 14967 | |
| 14968 | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); |
| 14969 | if (type_is_invalid(casted_op1->value->type)) |
| 14970 | return ira->codegen->invalid_instruction; |
| 14971 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, dest_type); |
| 14972 | if (type_is_invalid(casted_op2->value->type)) |
| 14973 | return ira->codegen->invalid_instruction; |
| 14974 | return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); |
| 14975 | } |
| 14976 | |
| 14977 | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 14517 | 14978 | IrInstruction *op1 = bin_op_instruction->op1->child; |
| 14518 | 14979 | if (type_is_invalid(op1->value->type)) |
| 14519 | 14980 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -14726,6 +15187,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 14726 | 15187 | return result; |
| 14727 | 15188 | } |
| 14728 | 15189 | |
| 15190 | if (type_is_numeric(op1->value->type) && type_is_numeric(op2->value->type)) { |
| 15191 | // This operation allows any combination of integer and float types, regardless of the |
| 15192 | // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for |
| 15193 | // numeric types. |
| 15194 | return ir_analyze_bin_op_cmp_numeric(ira, &bin_op_instruction->base, op1, op2, op_id); |
| 15195 | } |
| 15196 | |
| 14729 | 15197 | IrInstruction *instructions[] = {op1, op2}; |
| 14730 | 15198 | ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2); |
| 14731 | 15199 | if (type_is_invalid(resolved_type)) |
| ... | ... | @@ -14741,8 +15209,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 14741 | 15209 | case ZigTypeIdInt: |
| 14742 | 15210 | case ZigTypeIdFloat: |
| 14743 | 15211 | case ZigTypeIdVector: |
| 14744 | | operator_allowed = true; |
| 14745 | | break; |
| 15212 | zig_unreachable(); // handled with the type_is_numeric checks above |
| 14746 | 15213 | |
| 14747 | 15214 | case ZigTypeIdBool: |
| 14748 | 15215 | case ZigTypeIdMetaType: |
| ... | ... | @@ -14802,50 +15269,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 14802 | 15269 | } |
| 14803 | 15270 | |
| 14804 | 15271 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 14805 | | { |
| 14806 | | // Before resolving the values, we special case comparisons against zero. These can often be done |
| 14807 | | // without resolving lazy values, preventing potential dependency loops. |
| 14808 | | Cmp op1_cmp_zero; |
| 14809 | | if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, casted_op1->value, &op1_cmp_zero))) { |
| 14810 | | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 14811 | | return ira->codegen->invalid_instruction; |
| 14812 | | } |
| 14813 | | Cmp op2_cmp_zero; |
| 14814 | | if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, casted_op2->value, &op2_cmp_zero))) { |
| 14815 | | if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; |
| 14816 | | return ira->codegen->invalid_instruction; |
| 14817 | | } |
| 14818 | | bool can_cmp_zero = false; |
| 14819 | | Cmp cmp_result; |
| 14820 | | if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpEQ) { |
| 14821 | | can_cmp_zero = true; |
| 14822 | | cmp_result = CmpEQ; |
| 14823 | | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpEQ) { |
| 14824 | | can_cmp_zero = true; |
| 14825 | | cmp_result = CmpGT; |
| 14826 | | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpGT) { |
| 14827 | | can_cmp_zero = true; |
| 14828 | | cmp_result = CmpLT; |
| 14829 | | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpEQ) { |
| 14830 | | can_cmp_zero = true; |
| 14831 | | cmp_result = CmpLT; |
| 14832 | | } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpLT) { |
| 14833 | | can_cmp_zero = true; |
| 14834 | | cmp_result = CmpGT; |
| 14835 | | } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpGT) { |
| 14836 | | can_cmp_zero = true; |
| 14837 | | cmp_result = CmpLT; |
| 14838 | | } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpLT) { |
| 14839 | | can_cmp_zero = true; |
| 14840 | | cmp_result = CmpGT; |
| 14841 | | } |
| 14842 | | if (can_cmp_zero) { |
| 14843 | | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 14844 | | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 14845 | | } |
| 14846 | | } |
| 14847 | | never_mind_just_calculate_it_normally: |
| 14848 | | |
| 14849 | 15272 | ZigValue *op1_val = one_possible_value ? casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 14850 | 15273 | if (op1_val == nullptr) |
| 14851 | 15274 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -14870,43 +15293,6 @@ never_mind_just_calculate_it_normally: |
| 14870 | 15293 | return result; |
| 14871 | 15294 | } |
| 14872 | 15295 | |
| 14873 | | // some comparisons with unsigned numbers can be evaluated |
| 14874 | | if (resolved_type->id == ZigTypeIdInt && !resolved_type->data.integral.is_signed) { |
| 14875 | | ZigValue *known_left_val; |
| 14876 | | IrBinOp flipped_op_id; |
| 14877 | | if (instr_is_comptime(casted_op1)) { |
| 14878 | | known_left_val = ir_resolve_const(ira, casted_op1, UndefBad); |
| 14879 | | if (known_left_val == nullptr) |
| 14880 | | return ira->codegen->invalid_instruction; |
| 14881 | | |
| 14882 | | flipped_op_id = op_id; |
| 14883 | | } else if (instr_is_comptime(casted_op2)) { |
| 14884 | | known_left_val = ir_resolve_const(ira, casted_op2, UndefBad); |
| 14885 | | if (known_left_val == nullptr) |
| 14886 | | return ira->codegen->invalid_instruction; |
| 14887 | | |
| 14888 | | if (op_id == IrBinOpCmpLessThan) { |
| 14889 | | flipped_op_id = IrBinOpCmpGreaterThan; |
| 14890 | | } else if (op_id == IrBinOpCmpGreaterThan) { |
| 14891 | | flipped_op_id = IrBinOpCmpLessThan; |
| 14892 | | } else if (op_id == IrBinOpCmpLessOrEq) { |
| 14893 | | flipped_op_id = IrBinOpCmpGreaterOrEq; |
| 14894 | | } else if (op_id == IrBinOpCmpGreaterOrEq) { |
| 14895 | | flipped_op_id = IrBinOpCmpLessOrEq; |
| 14896 | | } else { |
| 14897 | | flipped_op_id = op_id; |
| 14898 | | } |
| 14899 | | } else { |
| 14900 | | known_left_val = nullptr; |
| 14901 | | } |
| 14902 | | if (known_left_val != nullptr && bigint_cmp_zero(&known_left_val->data.x_bigint) == CmpEQ && |
| 14903 | | (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan)) |
| 14904 | | { |
| 14905 | | bool answer = (flipped_op_id == IrBinOpCmpLessOrEq); |
| 14906 | | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 14907 | | } |
| 14908 | | } |
| 14909 | | |
| 14910 | 15296 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, |
| 14911 | 15297 | bin_op_instruction->base.scope, bin_op_instruction->base.source_node, |
| 14912 | 15298 | op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on); |
| ... | ... | @@ -23959,26 +24345,32 @@ static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInst |
| 23959 | 24345 | return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat); |
| 23960 | 24346 | } |
| 23961 | 24347 | |
| 24348 | static IrInstruction *ir_analyze_float_to_int(IrAnalyze *ira, IrInstruction *source_instr, |
| 24349 | ZigType *dest_type, IrInstruction *operand, AstNode *operand_source_node) |
| 24350 | { |
| 24351 | if (operand->value->type->id == ZigTypeIdComptimeInt) { |
| 24352 | return ir_implicit_cast(ira, operand, dest_type); |
| 24353 | } |
| 24354 | |
| 24355 | if (operand->value->type->id != ZigTypeIdFloat && operand->value->type->id != ZigTypeIdComptimeFloat) { |
| 24356 | ir_add_error_node(ira, operand_source_node, buf_sprintf("expected float type, found '%s'", |
| 24357 | buf_ptr(&operand->value->type->name))); |
| 24358 | return ira->codegen->invalid_instruction; |
| 24359 | } |
| 24360 | |
| 24361 | return ir_resolve_cast(ira, source_instr, operand, dest_type, CastOpFloatToInt); |
| 24362 | } |
| 24363 | |
| 23962 | 24364 | static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) { |
| 23963 | 24365 | ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); |
| 23964 | 24366 | if (type_is_invalid(dest_type)) |
| 23965 | 24367 | return ira->codegen->invalid_instruction; |
| 23966 | 24368 | |
| 23967 | | IrInstruction *target = instruction->target->child; |
| 23968 | | if (type_is_invalid(target->value->type)) |
| 24369 | IrInstruction *operand = instruction->target->child; |
| 24370 | if (type_is_invalid(operand->value->type)) |
| 23969 | 24371 | return ira->codegen->invalid_instruction; |
| 23970 | 24372 | |
| 23971 | | if (target->value->type->id == ZigTypeIdComptimeInt) { |
| 23972 | | return ir_implicit_cast(ira, target, dest_type); |
| 23973 | | } |
| 23974 | | |
| 23975 | | if (target->value->type->id != ZigTypeIdFloat && target->value->type->id != ZigTypeIdComptimeFloat) { |
| 23976 | | ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'", |
| 23977 | | buf_ptr(&target->value->type->name))); |
| 23978 | | return ira->codegen->invalid_instruction; |
| 23979 | | } |
| 23980 | | |
| 23981 | | return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt); |
| 24373 | return ir_analyze_float_to_int(ira, &instruction->base, dest_type, operand, instruction->target->source_node); |
| 23982 | 24374 | } |
| 23983 | 24375 | |
| 23984 | 24376 | static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) { |
| ... | ... | @@ -27111,13 +27503,13 @@ static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, I |
| 27111 | 27503 | return result; |
| 27112 | 27504 | } |
| 27113 | 27505 | |
| 27114 | | static void ir_eval_float_op(IrAnalyze *ira, IrInstructionFloatOp *source_instr, ZigType *float_type, |
| 27115 | | ZigValue *op, ZigValue *out_val) { |
| 27506 | static void ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, BuiltinFnId fop, ZigType *float_type, |
| 27507 | ZigValue *op, ZigValue *out_val) |
| 27508 | { |
| 27116 | 27509 | assert(ira && source_instr && float_type && out_val && op); |
| 27117 | 27510 | assert(float_type->id == ZigTypeIdFloat || |
| 27118 | 27511 | float_type->id == ZigTypeIdComptimeFloat); |
| 27119 | 27512 | |
| 27120 | | BuiltinFnId fop = source_instr->op; |
| 27121 | 27513 | unsigned bits; |
| 27122 | 27514 | |
| 27123 | 27515 | switch (float_type->id) { |
| ... | ... | @@ -27291,45 +27683,39 @@ static void ir_eval_float_op(IrAnalyze *ira, IrInstructionFloatOp *source_instr, |
| 27291 | 27683 | } |
| 27292 | 27684 | } |
| 27293 | 27685 | |
| 27294 | | static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) { |
| 27295 | | IrInstruction *type = instruction->type->child; |
| 27296 | | if (type_is_invalid(type->value->type)) |
| 27297 | | return ira->codegen->invalid_instruction; |
| 27298 | | |
| 27299 | | ZigType *expr_type = ir_resolve_type(ira, type); |
| 27300 | | if (type_is_invalid(expr_type)) |
| 27301 | | return ira->codegen->invalid_instruction; |
| 27302 | | |
| 27686 | static IrInstruction *ir_analyze_float_op(IrAnalyze *ira, IrInstruction *source_instr, |
| 27687 | ZigType *expr_type, AstNode *expr_type_src_node, IrInstruction *operand, BuiltinFnId op) |
| 27688 | { |
| 27303 | 27689 | // Only allow float types, and vectors of floats. |
| 27304 | 27690 | ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; |
| 27305 | 27691 | if (float_type->id != ZigTypeIdFloat && float_type->id != ZigTypeIdComptimeFloat) { |
| 27306 | | ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name))); |
| 27692 | ir_add_error_node(ira, expr_type_src_node, |
| 27693 | buf_sprintf("@%s does not support type '%s'", |
| 27694 | float_op_to_name(op, false), buf_ptr(&float_type->name))); |
| 27307 | 27695 | return ira->codegen->invalid_instruction; |
| 27308 | 27696 | } |
| 27309 | 27697 | |
| 27310 | | IrInstruction *op1 = instruction->op1->child; |
| 27311 | | if (type_is_invalid(op1->value->type)) |
| 27312 | | return ira->codegen->invalid_instruction; |
| 27313 | | |
| 27314 | | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, float_type); |
| 27315 | | if (type_is_invalid(casted_op1->value->type)) |
| 27698 | IrInstruction *casted_op = ir_implicit_cast(ira, operand, float_type); |
| 27699 | if (type_is_invalid(casted_op->value->type)) |
| 27316 | 27700 | return ira->codegen->invalid_instruction; |
| 27317 | 27701 | |
| 27318 | | if (instr_is_comptime(casted_op1)) { |
| 27319 | | // Our comptime 16-bit and 128-bit support is quite limited. |
| 27702 | if (instr_is_comptime(casted_op)) { |
| 27320 | 27703 | if ((float_type->id == ZigTypeIdComptimeFloat || |
| 27321 | 27704 | float_type->data.floating.bit_count == 16 || |
| 27322 | 27705 | float_type->data.floating.bit_count == 128) && |
| 27323 | | instruction->op != BuiltinFnIdSqrt) { |
| 27324 | | ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name))); |
| 27706 | op != BuiltinFnIdSqrt) |
| 27707 | { |
| 27708 | ir_add_error(ira, source_instr, |
| 27709 | buf_sprintf("compiler bug: TODO make @%s support type '%s'", |
| 27710 | float_op_to_name(op, false), buf_ptr(&float_type->name))); |
| 27325 | 27711 | return ira->codegen->invalid_instruction; |
| 27326 | 27712 | } |
| 27327 | 27713 | |
| 27328 | | ZigValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad); |
| 27714 | ZigValue *op1_const = ir_resolve_const(ira, casted_op, UndefBad); |
| 27329 | 27715 | if (!op1_const) |
| 27330 | 27716 | return ira->codegen->invalid_instruction; |
| 27331 | 27717 | |
| 27332 | | IrInstruction *result = ir_const(ira, &instruction->base, expr_type); |
| 27718 | IrInstruction *result = ir_const(ira, source_instr, expr_type); |
| 27333 | 27719 | ZigValue *out_val = result->value; |
| 27334 | 27720 | |
| 27335 | 27721 | if (expr_type->id == ZigTypeIdVector) { |
| ... | ... | @@ -27342,26 +27728,38 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct |
| 27342 | 27728 | ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i]; |
| 27343 | 27729 | assert(float_operand_op1->type == float_type); |
| 27344 | 27730 | assert(float_out_val->type == float_type); |
| 27345 | | ir_eval_float_op(ira, instruction, float_type, |
| 27346 | | op1_const, float_out_val); |
| 27731 | ir_eval_float_op(ira, source_instr, op, float_type, op1_const, float_out_val); |
| 27347 | 27732 | float_out_val->type = float_type; |
| 27348 | 27733 | } |
| 27349 | 27734 | out_val->type = expr_type; |
| 27350 | 27735 | out_val->special = ConstValSpecialStatic; |
| 27351 | 27736 | } else { |
| 27352 | | ir_eval_float_op(ira, instruction, float_type, op1_const, out_val); |
| 27737 | ir_eval_float_op(ira, source_instr, op, float_type, op1_const, out_val); |
| 27353 | 27738 | } |
| 27354 | 27739 | return result; |
| 27355 | 27740 | } |
| 27356 | 27741 | |
| 27357 | | ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base); |
| 27742 | ir_assert(float_type->id == ZigTypeIdFloat, source_instr); |
| 27358 | 27743 | |
| 27359 | | IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope, |
| 27360 | | instruction->base.source_node, nullptr, casted_op1, instruction->op); |
| 27744 | IrInstruction *result = ir_build_float_op(&ira->new_irb, source_instr->scope, |
| 27745 | source_instr->source_node, nullptr, casted_op, op); |
| 27361 | 27746 | result->value->type = expr_type; |
| 27362 | 27747 | return result; |
| 27363 | 27748 | } |
| 27364 | 27749 | |
| 27750 | static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) { |
| 27751 | ZigType *expr_type = ir_resolve_type(ira, instruction->type->child); |
| 27752 | if (type_is_invalid(expr_type)) |
| 27753 | return ira->codegen->invalid_instruction; |
| 27754 | |
| 27755 | IrInstruction *operand = instruction->op1->child; |
| 27756 | if (type_is_invalid(operand->value->type)) |
| 27757 | return ira->codegen->invalid_instruction; |
| 27758 | |
| 27759 | return ir_analyze_float_op(ira, &instruction->base, expr_type, instruction->type->source_node, |
| 27760 | operand, instruction->op); |
| 27761 | } |
| 27762 | |
| 27365 | 27763 | static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { |
| 27366 | 27764 | Error err; |
| 27367 | 27765 | |