| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #include "softfloat.hpp" |
| 16 | 16 | #include "util.hpp" |
| 17 | 17 | #include "mem_list.hpp" |
| 18 | #include "all_types.hpp" |
| 18 | 19 | |
| 19 | 20 | #include <errno.h> |
| 20 | 21 | |
| ... | ... | @@ -5099,6 +5100,17 @@ static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block |
| 5099 | 5100 | irb->current_basic_block = basic_block; |
| 5100 | 5101 | } |
| 5101 | 5102 | |
| 5103 | static void ir_append_basic_block_gen(IrBuilderGen *irb, IrBasicBlockGen *bb) { |
| 5104 | assert(!bb->already_appended); |
| 5105 | bb->already_appended = true; |
| 5106 | irb->exec->basic_block_list.append(bb); |
| 5107 | } |
| 5108 | |
| 5109 | static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { |
| 5110 | ir_append_basic_block_gen(irb, basic_block); |
| 5111 | ir_set_cursor_at_end_gen(irb, basic_block); |
| 5112 | } |
| 5113 | |
| 5102 | 5114 | static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { |
| 5103 | 5115 | basic_block->index = irb->exec->basic_block_list.length; |
| 5104 | 5116 | irb->exec->basic_block_list.append(basic_block); |
| ... | ... | @@ -13137,12 +13149,11 @@ static void ir_start_next_bb(IrAnalyze *ira) { |
| 13137 | 13149 | |
| 13138 | 13150 | static void ir_finish_bb(IrAnalyze *ira) { |
| 13139 | 13151 | if (!ira->new_irb.current_basic_block->already_appended) { |
| 13140 | | ira->new_irb.current_basic_block->already_appended = true; |
| 13152 | ir_append_basic_block_gen(&ira->new_irb, ira->new_irb.current_basic_block); |
| 13141 | 13153 | if (ira->codegen->verbose_ir) { |
| 13142 | 13154 | fprintf(stderr, "append new bb %s_%" PRIu32 "\n", ira->new_irb.current_basic_block->name_hint, |
| 13143 | 13155 | ira->new_irb.current_basic_block->debug_id); |
| 13144 | 13156 | } |
| 13145 | | ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block); |
| 13146 | 13157 | } |
| 13147 | 13158 | ira->instruction_index += 1; |
| 13148 | 13159 | while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) { |
| ... | ... | @@ -15849,12 +15860,12 @@ static void set_optional_payload(ZigValue *opt_val, ZigValue *payload) { |
| 15849 | 15860 | } |
| 15850 | 15861 | |
| 15851 | 15862 | static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, |
| 15852 | | ZigValue *op1_val, ZigValue *op2_val, IrInstSrcBinOp *bin_op_instruction, IrBinOp op_id, |
| 15863 | ZigValue *op1_val, ZigValue *op2_val, IrInst *source_instr, IrBinOp op_id, |
| 15853 | 15864 | bool one_possible_value) |
| 15854 | 15865 | { |
| 15855 | 15866 | if (op1_val->special == ConstValSpecialUndef || |
| 15856 | 15867 | op2_val->special == ConstValSpecialUndef) |
| 15857 | | return ir_const_undef(ira, &bin_op_instruction->base.base, resolved_type); |
| 15868 | return ir_const_undef(ira, source_instr, resolved_type); |
| 15858 | 15869 | if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { |
| 15859 | 15870 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| 15860 | 15871 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && |
| ... | ... | @@ -15874,7 +15885,7 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, |
| 15874 | 15885 | cmp_result = CmpEQ; |
| 15875 | 15886 | } |
| 15876 | 15887 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 15877 | | return ir_const_bool(ira, &bin_op_instruction->base.base, answer); |
| 15888 | return ir_const_bool(ira, source_instr, answer); |
| 15878 | 15889 | } |
| 15879 | 15890 | } else { |
| 15880 | 15891 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); |
| ... | ... | @@ -15886,11 +15897,55 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, |
| 15886 | 15897 | } else { |
| 15887 | 15898 | zig_unreachable(); |
| 15888 | 15899 | } |
| 15889 | | return ir_const_bool(ira, &bin_op_instruction->base.base, answer); |
| 15900 | return ir_const_bool(ira, source_instr, answer); |
| 15890 | 15901 | } |
| 15891 | 15902 | zig_unreachable(); |
| 15892 | 15903 | } |
| 15893 | 15904 | |
| 15905 | static IrInstGen *ir_try_evaluate_bin_op_cmp_const(IrAnalyze *ira, IrInst *source_instr, IrInstGen *op1, IrInstGen *op2, |
| 15906 | ZigType *resolved_type, IrBinOp op_id) |
| 15907 | { |
| 15908 | assert(op1->value->type == resolved_type && op2->value->type == resolved_type); |
| 15909 | bool one_possible_value; |
| 15910 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { |
| 15911 | case OnePossibleValueInvalid: |
| 15912 | return ira->codegen->invalid_inst_gen; |
| 15913 | case OnePossibleValueYes: |
| 15914 | one_possible_value = true; |
| 15915 | break; |
| 15916 | case OnePossibleValueNo: |
| 15917 | one_possible_value = false; |
| 15918 | break; |
| 15919 | } |
| 15920 | |
| 15921 | if (one_possible_value || (instr_is_comptime(op1) && instr_is_comptime(op2))) { |
| 15922 | ZigValue *op1_val = one_possible_value ? op1->value : ir_resolve_const(ira, op1, UndefBad); |
| 15923 | if (op1_val == nullptr) |
| 15924 | return ira->codegen->invalid_inst_gen; |
| 15925 | ZigValue *op2_val = one_possible_value ? op2->value : ir_resolve_const(ira, op2, UndefBad); |
| 15926 | if (op2_val == nullptr) |
| 15927 | return ira->codegen->invalid_inst_gen; |
| 15928 | if (resolved_type->id != ZigTypeIdVector) |
| 15929 | return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, source_instr, op_id, one_possible_value); |
| 15930 | IrInstGen *result = ir_const(ira, source_instr, |
| 15931 | get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool)); |
| 15932 | result->value->data.x_array.data.s_none.elements = |
| 15933 | ira->codegen->pass1_arena->allocate<ZigValue>(resolved_type->data.vector.len); |
| 15934 | |
| 15935 | expand_undef_array(ira->codegen, result->value); |
| 15936 | for (size_t i = 0;i < resolved_type->data.vector.len;i++) { |
| 15937 | IrInstGen *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type, |
| 15938 | &op1_val->data.x_array.data.s_none.elements[i], |
| 15939 | &op2_val->data.x_array.data.s_none.elements[i], |
| 15940 | source_instr, op_id, one_possible_value); |
| 15941 | copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], cur_res->value); |
| 15942 | } |
| 15943 | return result; |
| 15944 | } else { |
| 15945 | return nullptr; |
| 15946 | } |
| 15947 | } |
| 15948 | |
| 15894 | 15949 | // Returns ErrorNotLazy when the value cannot be determined |
| 15895 | 15950 | static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) { |
| 15896 | 15951 | Error err; |
| ... | ... | @@ -16425,6 +16480,188 @@ static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_i |
| 16425 | 16480 | return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); |
| 16426 | 16481 | } |
| 16427 | 16482 | |
| 16483 | static bool type_is_self_comparable(ZigType *ty, bool is_equality_cmp) { |
| 16484 | if (type_is_numeric(ty)) { |
| 16485 | return true; |
| 16486 | } |
| 16487 | switch (ty->id) { |
| 16488 | case ZigTypeIdInvalid: |
| 16489 | zig_unreachable(); |
| 16490 | |
| 16491 | case ZigTypeIdComptimeFloat: |
| 16492 | case ZigTypeIdComptimeInt: |
| 16493 | case ZigTypeIdInt: |
| 16494 | case ZigTypeIdFloat: |
| 16495 | zig_unreachable(); // handled with the type_is_numeric check above |
| 16496 | |
| 16497 | case ZigTypeIdVector: |
| 16498 | // Not every case is handled by the type_is_numeric check above, |
| 16499 | // vectors of bool trigger this code path |
| 16500 | case ZigTypeIdBool: |
| 16501 | case ZigTypeIdMetaType: |
| 16502 | case ZigTypeIdVoid: |
| 16503 | case ZigTypeIdErrorSet: |
| 16504 | case ZigTypeIdFn: |
| 16505 | case ZigTypeIdOpaque: |
| 16506 | case ZigTypeIdBoundFn: |
| 16507 | case ZigTypeIdEnum: |
| 16508 | case ZigTypeIdEnumLiteral: |
| 16509 | case ZigTypeIdAnyFrame: |
| 16510 | return is_equality_cmp; |
| 16511 | |
| 16512 | case ZigTypeIdPointer: |
| 16513 | return is_equality_cmp || (ty->data.pointer.ptr_len == PtrLenC); |
| 16514 | |
| 16515 | case ZigTypeIdUnreachable: |
| 16516 | case ZigTypeIdArray: |
| 16517 | case ZigTypeIdStruct: |
| 16518 | case ZigTypeIdUndefined: |
| 16519 | case ZigTypeIdNull: |
| 16520 | case ZigTypeIdErrorUnion: |
| 16521 | case ZigTypeIdUnion: |
| 16522 | case ZigTypeIdFnFrame: |
| 16523 | return false; |
| 16524 | |
| 16525 | case ZigTypeIdOptional: |
| 16526 | return is_equality_cmp && get_src_ptr_type(ty) != nullptr; |
| 16527 | } |
| 16528 | zig_unreachable(); |
| 16529 | } |
| 16530 | |
| 16531 | static IrInstGen *ir_try_evaluate_cmp_optional_non_optional_const(IrAnalyze *ira, IrInst *source_instr, ZigType *child_type, |
| 16532 | IrInstGen *optional, IrInstGen *non_optional, IrBinOp op_id) |
| 16533 | { |
| 16534 | assert(optional->value->type->id == ZigTypeIdOptional); |
| 16535 | assert(optional->value->type->data.maybe.child_type == non_optional->value->type); |
| 16536 | assert(non_optional->value->type == child_type); |
| 16537 | assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 16538 | |
| 16539 | if (instr_is_comptime(optional) && instr_is_comptime(non_optional)) { |
| 16540 | ZigValue *optional_val = ir_resolve_const(ira, optional, UndefBad); |
| 16541 | if (!optional_val) { |
| 16542 | return ira->codegen->invalid_inst_gen; |
| 16543 | } |
| 16544 | |
| 16545 | ZigValue *non_optional_val = ir_resolve_const(ira, non_optional, UndefBad); |
| 16546 | if (!non_optional_val) { |
| 16547 | return ira->codegen->invalid_inst_gen; |
| 16548 | } |
| 16549 | |
| 16550 | if (!optional_value_is_null(optional_val)) { |
| 16551 | IrInstGen *optional_unwrapped = ir_analyze_optional_value_payload_value(ira, source_instr, optional, false); |
| 16552 | if (type_is_invalid(optional_unwrapped->value->type)) { |
| 16553 | return ira->codegen->invalid_inst_gen; |
| 16554 | } |
| 16555 | |
| 16556 | IrInstGen *ret = ir_try_evaluate_bin_op_cmp_const(ira, source_instr, optional_unwrapped, non_optional, child_type, op_id); |
| 16557 | assert(ret != nullptr); |
| 16558 | return ret; |
| 16559 | } |
| 16560 | return ir_const_bool(ira, source_instr, (op_id != IrBinOpCmpEq)); |
| 16561 | } else { |
| 16562 | return nullptr; |
| 16563 | } |
| 16564 | } |
| 16565 | |
| 16566 | static IrInstGen *ir_evaluate_cmp_optional_non_optional(IrAnalyze *ira, IrInst *source_instr, ZigType *child_type, |
| 16567 | IrInstGen *optional, IrInstGen *non_optional, IrBinOp op_id) |
| 16568 | { |
| 16569 | assert(optional->value->type->id == ZigTypeIdOptional); |
| 16570 | assert(optional->value->type->data.maybe.child_type == non_optional->value->type); |
| 16571 | assert(non_optional->value->type == child_type); |
| 16572 | assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 16573 | |
| 16574 | ZigType *result_type = ira->codegen->builtin_types.entry_bool; |
| 16575 | ir_append_basic_block_gen(&ira->new_irb, ira->new_irb.current_basic_block); |
| 16576 | |
| 16577 | IrBasicBlockGen *null_block = ir_create_basic_block_gen(ira, source_instr->scope, "CmpOptionalNonOptionalOptionalNull"); |
| 16578 | IrBasicBlockGen *non_null_block = ir_create_basic_block_gen(ira, source_instr->scope, "CmpOptionalNonOptionalOptionalNotNull"); |
| 16579 | IrBasicBlockGen *end_block = ir_create_basic_block_gen(ira, source_instr->scope, "CmpOptionalNonOptionalEnd"); |
| 16580 | |
| 16581 | IrInstGen *is_non_null = ir_build_test_non_null_gen(ira, source_instr, optional); |
| 16582 | ir_build_cond_br_gen(ira, source_instr, is_non_null, non_null_block, null_block); |
| 16583 | |
| 16584 | ir_set_cursor_at_end_and_append_block_gen(&ira->new_irb, non_null_block); |
| 16585 | IrInstGen *optional_unwrapped = ir_analyze_optional_value_payload_value(ira, source_instr, optional, false); |
| 16586 | if (type_is_invalid(optional_unwrapped->value->type)) { |
| 16587 | return ira->codegen->invalid_inst_gen; |
| 16588 | } |
| 16589 | IrInstGen *non_null_cmp_result = ir_build_bin_op_gen(ira, source_instr, result_type, op_id, |
| 16590 | optional_unwrapped, non_optional, false); // safety check unnecessary for comparison operators |
| 16591 | ir_build_br_gen(ira, source_instr, end_block); |
| 16592 | |
| 16593 | |
| 16594 | ir_set_cursor_at_end_and_append_block_gen(&ira->new_irb, null_block); |
| 16595 | IrInstGen *null_result = ir_const_bool(ira, source_instr, (op_id != IrBinOpCmpEq)); |
| 16596 | ir_build_br_gen(ira, source_instr, end_block); |
| 16597 | |
| 16598 | ir_set_cursor_at_end_gen(&ira->new_irb, end_block); |
| 16599 | int incoming_count = 2; |
| 16600 | IrBasicBlockGen **incoming_blocks = heap::c_allocator.allocate_nonzero<IrBasicBlockGen *>(incoming_count); |
| 16601 | incoming_blocks[0] = null_block; |
| 16602 | incoming_blocks[1] = non_null_block; |
| 16603 | IrInstGen **incoming_values = heap::c_allocator.allocate_nonzero<IrInstGen *>(incoming_count); |
| 16604 | incoming_values[0] = null_result; |
| 16605 | incoming_values[1] = non_null_cmp_result; |
| 16606 | |
| 16607 | return ir_build_phi_gen(ira, source_instr, incoming_count, incoming_blocks, incoming_values, result_type); |
| 16608 | } |
| 16609 | |
| 16610 | static IrInstGen *ir_analyze_cmp_optional_non_optional(IrAnalyze *ira, IrInst *source_instr, |
| 16611 | IrInstGen *op1, IrInstGen *op2, IrInstGen *optional, IrBinOp op_id) |
| 16612 | { |
| 16613 | assert(op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 16614 | assert(optional->value->type->id == ZigTypeIdOptional); |
| 16615 | assert(get_src_ptr_type(optional->value->type) == nullptr); |
| 16616 | |
| 16617 | IrInstGen *non_optional; |
| 16618 | if (op1 == optional) { |
| 16619 | non_optional = op2; |
| 16620 | } else if (op2 == optional) { |
| 16621 | non_optional = op1; |
| 16622 | } else { |
| 16623 | zig_unreachable(); |
| 16624 | } |
| 16625 | |
| 16626 | ZigType *child_type = optional->value->type->data.maybe.child_type; |
| 16627 | bool child_type_matches = (child_type == non_optional->value->type); |
| 16628 | if (!child_type_matches || !type_is_self_comparable(child_type, true)) { |
| 16629 | ErrorMsg *msg = ir_add_error_node(ira, source_instr->source_node, buf_sprintf("cannot compare types '%s' and '%s'", |
| 16630 | buf_ptr(&op1->value->type->name), |
| 16631 | buf_ptr(&op2->value->type->name))); |
| 16632 | |
| 16633 | if (!child_type_matches) { |
| 16634 | if (non_optional->value->type->id == ZigTypeIdOptional) { |
| 16635 | add_error_note(ira->codegen, msg, source_instr->source_node, buf_sprintf( |
| 16636 | "optional to optional comparison is only supported for optional pointer types")); |
| 16637 | } else { |
| 16638 | add_error_note(ira->codegen, msg, source_instr->source_node, |
| 16639 | buf_sprintf("optional child type '%s' must be the same as non-optional type '%s'", |
| 16640 | buf_ptr(&child_type->name), |
| 16641 | buf_ptr(&non_optional->value->type->name))); |
| 16642 | } |
| 16643 | } else { |
| 16644 | add_error_note(ira->codegen, msg, source_instr->source_node, |
| 16645 | buf_sprintf("operator not supported for type '%s'", |
| 16646 | buf_ptr(&child_type->name))); |
| 16647 | } |
| 16648 | return ira->codegen->invalid_inst_gen; |
| 16649 | } |
| 16650 | |
| 16651 | if (child_type->id == ZigTypeIdVector) { |
| 16652 | ir_add_error_node(ira, source_instr->source_node, buf_sprintf("TODO add comparison of optional vector")); |
| 16653 | return ira->codegen->invalid_inst_gen; |
| 16654 | } |
| 16655 | |
| 16656 | if (IrInstGen *const_result = ir_try_evaluate_cmp_optional_non_optional_const(ira, source_instr, child_type, |
| 16657 | optional, non_optional, op_id)) |
| 16658 | { |
| 16659 | return const_result; |
| 16660 | } |
| 16661 | |
| 16662 | return ir_evaluate_cmp_optional_non_optional(ira, source_instr, child_type, optional, non_optional, op_id); |
| 16663 | } |
| 16664 | |
| 16428 | 16665 | static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { |
| 16429 | 16666 | IrInstGen *op1 = bin_op_instruction->op1->child; |
| 16430 | 16667 | if (type_is_invalid(op1->value->type)) |
| ... | ... | @@ -16501,6 +16738,14 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16501 | 16738 | } else { |
| 16502 | 16739 | return is_non_null; |
| 16503 | 16740 | } |
| 16741 | } else if (is_equality_cmp && |
| 16742 | (op1->value->type->id == ZigTypeIdOptional && get_src_ptr_type(op1->value->type) == nullptr)) |
| 16743 | { |
| 16744 | return ir_analyze_cmp_optional_non_optional(ira, &bin_op_instruction->base.base, op1, op2, op1, op_id); |
| 16745 | } else if(is_equality_cmp && |
| 16746 | (op2->value->type->id == ZigTypeIdOptional && get_src_ptr_type(op2->value->type) == nullptr)) |
| 16747 | { |
| 16748 | return ir_analyze_cmp_optional_non_optional(ira, &bin_op_instruction->base.base, op1, op2, op2, op_id); |
| 16504 | 16749 | } else if (op1->value->type->id == ZigTypeIdNull || op2->value->type->id == ZigTypeIdNull) { |
| 16505 | 16750 | ZigType *non_null_type = (op1->value->type->id == ZigTypeIdNull) ? op2->value->type : op1->value->type; |
| 16506 | 16751 | ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", |
| ... | ... | @@ -16642,51 +16887,8 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16642 | 16887 | if (type_is_invalid(resolved_type)) |
| 16643 | 16888 | return ira->codegen->invalid_inst_gen; |
| 16644 | 16889 | |
| 16645 | | bool operator_allowed; |
| 16646 | | switch (resolved_type->id) { |
| 16647 | | case ZigTypeIdInvalid: |
| 16648 | | zig_unreachable(); // handled above |
| 16649 | | |
| 16650 | | case ZigTypeIdComptimeFloat: |
| 16651 | | case ZigTypeIdComptimeInt: |
| 16652 | | case ZigTypeIdInt: |
| 16653 | | case ZigTypeIdFloat: |
| 16654 | | zig_unreachable(); // handled with the type_is_numeric checks above |
| 16655 | | |
| 16656 | | case ZigTypeIdVector: |
| 16657 | | // Not every case is handled by the type_is_numeric checks above, |
| 16658 | | // vectors of bool trigger this code path |
| 16659 | | case ZigTypeIdBool: |
| 16660 | | case ZigTypeIdMetaType: |
| 16661 | | case ZigTypeIdVoid: |
| 16662 | | case ZigTypeIdErrorSet: |
| 16663 | | case ZigTypeIdFn: |
| 16664 | | case ZigTypeIdOpaque: |
| 16665 | | case ZigTypeIdBoundFn: |
| 16666 | | case ZigTypeIdEnum: |
| 16667 | | case ZigTypeIdEnumLiteral: |
| 16668 | | case ZigTypeIdAnyFrame: |
| 16669 | | operator_allowed = is_equality_cmp; |
| 16670 | | break; |
| 16671 | | |
| 16672 | | case ZigTypeIdPointer: |
| 16673 | | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC); |
| 16674 | | break; |
| 16890 | bool operator_allowed = type_is_self_comparable(resolved_type, is_equality_cmp); |
| 16675 | 16891 | |
| 16676 | | case ZigTypeIdUnreachable: |
| 16677 | | case ZigTypeIdArray: |
| 16678 | | case ZigTypeIdStruct: |
| 16679 | | case ZigTypeIdUndefined: |
| 16680 | | case ZigTypeIdNull: |
| 16681 | | case ZigTypeIdErrorUnion: |
| 16682 | | case ZigTypeIdUnion: |
| 16683 | | case ZigTypeIdFnFrame: |
| 16684 | | operator_allowed = false; |
| 16685 | | break; |
| 16686 | | case ZigTypeIdOptional: |
| 16687 | | operator_allowed = is_equality_cmp && get_src_ptr_type(resolved_type) != nullptr; |
| 16688 | | break; |
| 16689 | | } |
| 16690 | 16892 | if (!operator_allowed) { |
| 16691 | 16893 | ir_add_error_node(ira, source_node, |
| 16692 | 16894 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| ... | ... | @@ -16701,41 +16903,10 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16701 | 16903 | if (type_is_invalid(casted_op2->value->type)) |
| 16702 | 16904 | return ira->codegen->invalid_inst_gen; |
| 16703 | 16905 | |
| 16704 | | bool one_possible_value; |
| 16705 | | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { |
| 16706 | | case OnePossibleValueInvalid: |
| 16707 | | return ira->codegen->invalid_inst_gen; |
| 16708 | | case OnePossibleValueYes: |
| 16709 | | one_possible_value = true; |
| 16710 | | break; |
| 16711 | | case OnePossibleValueNo: |
| 16712 | | one_possible_value = false; |
| 16713 | | break; |
| 16714 | | } |
| 16715 | | |
| 16716 | | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 16717 | | ZigValue *op1_val = one_possible_value ? casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 16718 | | if (op1_val == nullptr) |
| 16719 | | return ira->codegen->invalid_inst_gen; |
| 16720 | | ZigValue *op2_val = one_possible_value ? casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad); |
| 16721 | | if (op2_val == nullptr) |
| 16722 | | return ira->codegen->invalid_inst_gen; |
| 16723 | | if (resolved_type->id != ZigTypeIdVector) |
| 16724 | | return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, bin_op_instruction, op_id, one_possible_value); |
| 16725 | | IrInstGen *result = ir_const(ira, &bin_op_instruction->base.base, |
| 16726 | | get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool)); |
| 16727 | | result->value->data.x_array.data.s_none.elements = |
| 16728 | | ira->codegen->pass1_arena->allocate<ZigValue>(resolved_type->data.vector.len); |
| 16729 | | |
| 16730 | | expand_undef_array(ira->codegen, result->value); |
| 16731 | | for (size_t i = 0;i < resolved_type->data.vector.len;i++) { |
| 16732 | | IrInstGen *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type, |
| 16733 | | &op1_val->data.x_array.data.s_none.elements[i], |
| 16734 | | &op2_val->data.x_array.data.s_none.elements[i], |
| 16735 | | bin_op_instruction, op_id, one_possible_value); |
| 16736 | | copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], cur_res->value); |
| 16737 | | } |
| 16738 | | return result; |
| 16906 | IrInstGen *resolve_const_result = ir_try_evaluate_bin_op_cmp_const(ira, &bin_op_instruction->base.base, casted_op1, |
| 16907 | casted_op2, resolved_type, op_id); |
| 16908 | if (resolve_const_result != nullptr) { |
| 16909 | return resolve_const_result; |
| 16739 | 16910 | } |
| 16740 | 16911 | |
| 16741 | 16912 | ZigType *res_type = (resolved_type->id == ZigTypeIdVector) ? |