| ... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
| 15 | #include "softfloat.hpp" | 15 | #include "softfloat.hpp" |
| 16 | #include "util.hpp" | 16 | #include "util.hpp" |
| 17 | #include "mem_list.hpp" | 17 | #include "mem_list.hpp" |
| | 18 | #include "all_types.hpp" |
| 18 | | 19 | |
| 19 | #include <errno.h> | 20 | #include <errno.h> |
| 20 | | 21 | |
| ... | @@ -5099,6 +5100,17 @@ static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block | ... | @@ -5099,6 +5100,17 @@ static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block |
| 5099 | irb->current_basic_block = basic_block; | 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 | static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { | 5114 | static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { |
| 5103 | basic_block->index = irb->exec->basic_block_list.length; | 5115 | basic_block->index = irb->exec->basic_block_list.length; |
| 5104 | irb->exec->basic_block_list.append(basic_block); | 5116 | irb->exec->basic_block_list.append(basic_block); |
| ... | @@ -13137,12 +13149,11 @@ static void ir_start_next_bb(IrAnalyze *ira) { | ... | @@ -13137,12 +13149,11 @@ static void ir_start_next_bb(IrAnalyze *ira) { |
| 13137 | | 13149 | |
| 13138 | static void ir_finish_bb(IrAnalyze *ira) { | 13150 | static void ir_finish_bb(IrAnalyze *ira) { |
| 13139 | if (!ira->new_irb.current_basic_block->already_appended) { | 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 | if (ira->codegen->verbose_ir) { | 13153 | if (ira->codegen->verbose_ir) { |
| 13142 | fprintf(stderr, "append new bb %s_%" PRIu32 "\n", ira->new_irb.current_basic_block->name_hint, | 13154 | fprintf(stderr, "append new bb %s_%" PRIu32 "\n", ira->new_irb.current_basic_block->name_hint, |
| 13143 | ira->new_irb.current_basic_block->debug_id); | 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 | ira->instruction_index += 1; | 13158 | ira->instruction_index += 1; |
| 13148 | while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) { | 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,12 +15860,12 @@ static void set_optional_payload(ZigValue *opt_val, ZigValue *payload) { |
| 15849 | } | 15860 | } |
| 15850 | | 15861 | |
| 15851 | static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, | 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 | bool one_possible_value) | 15864 | bool one_possible_value) |
| 15854 | { | 15865 | { |
| 15855 | if (op1_val->special == ConstValSpecialUndef || | 15866 | if (op1_val->special == ConstValSpecialUndef || |
| 15856 | op2_val->special == ConstValSpecialUndef) | 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 | if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { | 15869 | if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { |
| 15859 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | 15870 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| 15860 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && | 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,7 +15885,7 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, |
| 15874 | cmp_result = CmpEQ; | 15885 | cmp_result = CmpEQ; |
| 15875 | } | 15886 | } |
| 15876 | bool answer = resolve_cmp_op_id(op_id, cmp_result); | 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 | } else { | 15890 | } else { |
| 15880 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); | 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,11 +15897,55 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, |
| 15886 | } else { | 15897 | } else { |
| 15887 | zig_unreachable(); | 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 | zig_unreachable(); | 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 | // Returns ErrorNotLazy when the value cannot be determined | 15949 | // Returns ErrorNotLazy when the value cannot be determined |
| 15895 | static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) { | 15950 | static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) { |
| 15896 | Error err; | 15951 | Error err; |
| ... | @@ -16425,6 +16480,188 @@ static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_i | ... | @@ -16425,6 +16480,188 @@ static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_i |
| 16425 | return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); | 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 | static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { | 16665 | static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { |
| 16429 | IrInstGen *op1 = bin_op_instruction->op1->child; | 16666 | IrInstGen *op1 = bin_op_instruction->op1->child; |
| 16430 | if (type_is_invalid(op1->value->type)) | 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,6 +16738,14 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16501 | } else { | 16738 | } else { |
| 16502 | return is_non_null; | 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 | } else if (op1->value->type->id == ZigTypeIdNull || op2->value->type->id == ZigTypeIdNull) { | 16749 | } else if (op1->value->type->id == ZigTypeIdNull || op2->value->type->id == ZigTypeIdNull) { |
| 16505 | ZigType *non_null_type = (op1->value->type->id == ZigTypeIdNull) ? op2->value->type : op1->value->type; | 16750 | ZigType *non_null_type = (op1->value->type->id == ZigTypeIdNull) ? op2->value->type : op1->value->type; |
| 16506 | ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", | 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,51 +16887,8 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16642 | if (type_is_invalid(resolved_type)) | 16887 | if (type_is_invalid(resolved_type)) |
| 16643 | return ira->codegen->invalid_inst_gen; | 16888 | return ira->codegen->invalid_inst_gen; |
| 16644 | | 16889 | |
| 16645 | bool operator_allowed; | 16890 | bool operator_allowed = type_is_self_comparable(resolved_type, is_equality_cmp); |
| 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; | | |
| 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 | if (!operator_allowed) { | 16892 | if (!operator_allowed) { |
| 16691 | ir_add_error_node(ira, source_node, | 16893 | ir_add_error_node(ira, source_node, |
| 16692 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 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,41 +16903,10 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i |
| 16701 | if (type_is_invalid(casted_op2->value->type)) | 16903 | if (type_is_invalid(casted_op2->value->type)) |
| 16702 | return ira->codegen->invalid_inst_gen; | 16904 | return ira->codegen->invalid_inst_gen; |
| 16703 | | 16905 | |
| 16704 | bool one_possible_value; | 16906 | IrInstGen *resolve_const_result = ir_try_evaluate_bin_op_cmp_const(ira, &bin_op_instruction->base.base, casted_op1, |
| 16705 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { | 16907 | casted_op2, resolved_type, op_id); |
| 16706 | case OnePossibleValueInvalid: | 16908 | if (resolve_const_result != nullptr) { |
| 16707 | return ira->codegen->invalid_inst_gen; | 16909 | return resolve_const_result; |
| 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; | | |
| 16739 | } | 16910 | } |
| 16740 | | 16911 | |
| 16741 | ZigType *res_type = (resolved_type->id == ZigTypeIdVector) ? | 16912 | ZigType *res_type = (resolved_type->id == ZigTypeIdVector) ? |