| ... | @@ -11682,28 +11682,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -11682,28 +11682,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 11682 | } | 11682 | } |
| 11683 | | 11683 | |
| 11684 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { | 11684 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { |
| 11685 | if (op_id == IrBinOpCmpEq) { | 11685 | switch (op_id) { |
| 11686 | return cmp == CmpEQ; | 11686 | case IrBinOpCmpEq: |
| 11687 | } else if (op_id == IrBinOpCmpNotEq) { | 11687 | return cmp == CmpEQ; |
| 11688 | return cmp != CmpEQ; | 11688 | case IrBinOpCmpNotEq: |
| 11689 | } else if (op_id == IrBinOpCmpLessThan) { | 11689 | return cmp != CmpEQ; |
| 11690 | return cmp == CmpLT; | 11690 | case IrBinOpCmpLessThan: |
| 11691 | } else if (op_id == IrBinOpCmpGreaterThan) { | 11691 | return cmp == CmpLT; |
| 11692 | return cmp == CmpGT; | 11692 | case IrBinOpCmpGreaterThan: |
| 11693 | } else if (op_id == IrBinOpCmpLessOrEq) { | 11693 | return cmp == CmpGT; |
| 11694 | return cmp != CmpGT; | 11694 | case IrBinOpCmpLessOrEq: |
| 11695 | } else if (op_id == IrBinOpCmpGreaterOrEq) { | 11695 | return cmp != CmpGT; |
| 11696 | return cmp != CmpLT; | 11696 | case IrBinOpCmpGreaterOrEq: |
| 11697 | } else { | 11697 | return cmp != CmpLT; |
| 11698 | zig_unreachable(); | 11698 | default: |
| | 11699 | zig_unreachable(); |
| 11699 | } | 11700 | } |
| 11700 | } | 11701 | } |
| 11701 | | 11702 | |
| 11702 | static bool optional_value_is_null(ConstExprValue *val) { | 11703 | static bool optional_value_is_null(ConstExprValue *val) { |
| 11703 | assert(val->special == ConstValSpecialStatic); | 11704 | assert(val->special == ConstValSpecialStatic); |
| 11704 | if (get_codegen_ptr_type(val->type) != nullptr) { | 11705 | if (get_codegen_ptr_type(val->type) != nullptr) { |
| 11705 | return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | 11706 | if (val->data.x_ptr.special == ConstPtrSpecialNull) { |
| 11706 | val->data.x_ptr.data.hard_coded_addr.addr == 0; | 11707 | return true; |
| | 11708 | } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| | 11709 | return val->data.x_ptr.data.hard_coded_addr.addr == 0; |
| | 11710 | } else { |
| | 11711 | return false; |
| | 11712 | } |
| 11707 | } else if (is_opt_err_set(val->type)) { | 11713 | } else if (is_opt_err_set(val->type)) { |
| 11708 | return val->data.x_err_set == nullptr; | 11714 | return val->data.x_err_set == nullptr; |
| 11709 | } else { | 11715 | } else { |
| ... | @@ -11879,7 +11885,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11879,7 +11885,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11879 | break; | 11885 | break; |
| 11880 | | 11886 | |
| 11881 | case ZigTypeIdPointer: | 11887 | case ZigTypeIdPointer: |
| 11882 | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len != PtrLenSingle); | 11888 | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC); |
| 11883 | break; | 11889 | break; |
| 11884 | | 11890 | |
| 11885 | case ZigTypeIdUnreachable: | 11891 | case ZigTypeIdUnreachable: |
| ... | @@ -11929,15 +11935,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11929,15 +11935,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11929 | if (op2_val == nullptr) | 11935 | if (op2_val == nullptr) |
| 11930 | return ira->codegen->invalid_instruction; | 11936 | return ira->codegen->invalid_instruction; |
| 11931 | | 11937 | |
| 11932 | bool answer; | | |
| 11933 | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { | 11938 | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { |
| 11934 | Cmp cmp_result = float_cmp(op1_val, op2_val); | 11939 | Cmp cmp_result = float_cmp(op1_val, op2_val); |
| 11935 | answer = resolve_cmp_op_id(op_id, cmp_result); | 11940 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| | 11941 | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 11936 | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { | 11942 | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { |
| 11937 | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); | 11943 | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11938 | answer = resolve_cmp_op_id(op_id, cmp_result); | 11944 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| | 11945 | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| | 11946 | } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { |
| | 11947 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| | 11948 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && |
| | 11949 | (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| | 11950 | op2_val->data.x_ptr.special == ConstPtrSpecialNull)) |
| | 11951 | { |
| | 11952 | uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ? |
| | 11953 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; |
| | 11954 | uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ? |
| | 11955 | 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr; |
| | 11956 | Cmp cmp_result; |
| | 11957 | if (op1_addr > op2_addr) { |
| | 11958 | cmp_result = CmpGT; |
| | 11959 | } else if (op1_addr < op2_addr) { |
| | 11960 | cmp_result = CmpLT; |
| | 11961 | } else { |
| | 11962 | cmp_result = CmpEQ; |
| | 11963 | } |
| | 11964 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| | 11965 | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| | 11966 | } |
| 11939 | } else { | 11967 | } else { |
| 11940 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); | 11968 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); |
| | 11969 | bool answer; |
| 11941 | if (op_id == IrBinOpCmpEq) { | 11970 | if (op_id == IrBinOpCmpEq) { |
| 11942 | answer = are_equal; | 11971 | answer = are_equal; |
| 11943 | } else if (op_id == IrBinOpCmpNotEq) { | 11972 | } else if (op_id == IrBinOpCmpNotEq) { |
| ... | @@ -11945,9 +11974,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11945,9 +11974,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11945 | } else { | 11974 | } else { |
| 11946 | zig_unreachable(); | 11975 | zig_unreachable(); |
| 11947 | } | 11976 | } |
| | 11977 | return ir_const_bool(ira, &bin_op_instruction->base, answer); |
| 11948 | } | 11978 | } |
| 11949 | | | |
| 11950 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | | |
| 11951 | } | 11979 | } |
| 11952 | | 11980 | |
| 11953 | // some comparisons with unsigned numbers can be evaluated | 11981 | // some comparisons with unsigned numbers can be evaluated |
| ... | @@ -12363,6 +12391,8 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { | ... | @@ -12363,6 +12391,8 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { |
| 12363 | } | 12391 | } |
| 12364 | | 12392 | |
| 12365 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 12393 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| | 12394 | Error err; |
| | 12395 | |
| 12366 | IrInstruction *op1 = instruction->op1->child; | 12396 | IrInstruction *op1 = instruction->op1->child; |
| 12367 | if (type_is_invalid(op1->value.type)) | 12397 | if (type_is_invalid(op1->value.type)) |
| 12368 | return ira->codegen->invalid_instruction; | 12398 | return ira->codegen->invalid_instruction; |
| ... | @@ -12376,9 +12406,42 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -12376,9 +12406,42 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12376 | // look for pointer math | 12406 | // look for pointer math |
| 12377 | if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) { | 12407 | if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) { |
| 12378 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); | 12408 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); |
| 12379 | if (casted_op2 == ira->codegen->invalid_instruction) | 12409 | if (type_is_invalid(casted_op2->value.type)) |
| 12380 | return ira->codegen->invalid_instruction; | 12410 | return ira->codegen->invalid_instruction; |
| 12381 | | 12411 | |
| | 12412 | if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) { |
| | 12413 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); |
| | 12414 | result->value.special = ConstValSpecialUndef; |
| | 12415 | return result; |
| | 12416 | } |
| | 12417 | if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic && |
| | 12418 | (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| | 12419 | op1->value.data.x_ptr.special == ConstPtrSpecialNull)) |
| | 12420 | { |
| | 12421 | uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ? |
| | 12422 | 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr; |
| | 12423 | uint64_t elem_offset; |
| | 12424 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) |
| | 12425 | return ira->codegen->invalid_instruction; |
| | 12426 | ZigType *elem_type = op1->value.type->data.pointer.child_type; |
| | 12427 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) |
| | 12428 | return ira->codegen->invalid_instruction; |
| | 12429 | uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; |
| | 12430 | uint64_t new_addr; |
| | 12431 | if (op_id == IrBinOpAdd) { |
| | 12432 | new_addr = start_addr + byte_offset; |
| | 12433 | } else if (op_id == IrBinOpSub) { |
| | 12434 | new_addr = start_addr - byte_offset; |
| | 12435 | } else { |
| | 12436 | zig_unreachable(); |
| | 12437 | } |
| | 12438 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); |
| | 12439 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| | 12440 | result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar; |
| | 12441 | result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr; |
| | 12442 | return result; |
| | 12443 | } |
| | 12444 | |
| 12382 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 12445 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| 12383 | instruction->base.source_node, op_id, op1, casted_op2, true); | 12446 | instruction->base.source_node, op_id, op1, casted_op2, true); |
| 12384 | result->value.type = op1->value.type; | 12447 | result->value.type = op1->value.type; |