| ... | @@ -10494,6 +10494,50 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -10494,6 +10494,50 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10494 | continue; | 10494 | continue; |
| 10495 | } | 10495 | } |
| 10496 | | 10496 | |
| | 10497 | // *[N]T to []T |
| | 10498 | // *[N]T to E![]T |
| | 10499 | if (cur_type->id == ZigTypeIdPointer && |
| | 10500 | cur_type->data.pointer.child_type->id == ZigTypeIdArray && |
| | 10501 | ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) || |
| | 10502 | is_slice(prev_type))) |
| | 10503 | { |
| | 10504 | ZigType *array_type = cur_type->data.pointer.child_type; |
| | 10505 | ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ? |
| | 10506 | prev_type->data.error_union.payload_type : prev_type; |
| | 10507 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; |
| | 10508 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| | 10509 | types_match_const_cast_only(ira, |
| | 10510 | slice_ptr_type->data.pointer.child_type, |
| | 10511 | array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) |
| | 10512 | { |
| | 10513 | convert_to_const_slice = false; |
| | 10514 | continue; |
| | 10515 | } |
| | 10516 | } |
| | 10517 | |
| | 10518 | // *[N]T to []T |
| | 10519 | // *[N]T to E![]T |
| | 10520 | if (prev_type->id == ZigTypeIdPointer && |
| | 10521 | prev_type->data.pointer.child_type->id == ZigTypeIdArray && |
| | 10522 | ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) || |
| | 10523 | is_slice(cur_type))) |
| | 10524 | { |
| | 10525 | ZigType *array_type = prev_type->data.pointer.child_type; |
| | 10526 | ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ? |
| | 10527 | cur_type->data.error_union.payload_type : cur_type; |
| | 10528 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; |
| | 10529 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| | 10530 | types_match_const_cast_only(ira, |
| | 10531 | slice_ptr_type->data.pointer.child_type, |
| | 10532 | array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) |
| | 10533 | { |
| | 10534 | prev_inst = cur_inst; |
| | 10535 | convert_to_const_slice = false; |
| | 10536 | continue; |
| | 10537 | } |
| | 10538 | } |
| | 10539 | |
| | 10540 | // [N]T to []T |
| 10497 | if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) && | 10541 | if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) && |
| 10498 | (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || | 10542 | (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || |
| 10499 | cur_type->data.array.len == 0) && | 10543 | cur_type->data.array.len == 0) && |
| ... | @@ -10505,6 +10549,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -10505,6 +10549,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10505 | continue; | 10549 | continue; |
| 10506 | } | 10550 | } |
| 10507 | | 10551 | |
| | 10552 | // [N]T to []T |
| 10508 | if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && | 10553 | if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && |
| 10509 | (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || | 10554 | (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || |
| 10510 | prev_type->data.array.len == 0) && | 10555 | prev_type->data.array.len == 0) && |
| ... | @@ -12642,12 +12687,71 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -12642,12 +12687,71 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 12642 | } | 12687 | } |
| 12643 | | 12688 | |
| 12644 | // *[N]T to []T | 12689 | // *[N]T to []T |
| 12645 | if (is_slice(wanted_type) && | 12690 | // *[N]T to E![]T |
| | 12691 | if ((is_slice(wanted_type) || |
| | 12692 | (wanted_type->id == ZigTypeIdErrorUnion && |
| | 12693 | is_slice(wanted_type->data.error_union.payload_type))) && |
| | 12694 | actual_type->id == ZigTypeIdPointer && |
| | 12695 | actual_type->data.pointer.ptr_len == PtrLenSingle && |
| | 12696 | actual_type->data.pointer.child_type->id == ZigTypeIdArray) |
| | 12697 | { |
| | 12698 | ZigType *slice_type = (wanted_type->id == ZigTypeIdErrorUnion) ? |
| | 12699 | wanted_type->data.error_union.payload_type : wanted_type; |
| | 12700 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; |
| | 12701 | assert(slice_ptr_type->id == ZigTypeIdPointer); |
| | 12702 | ZigType *array_type = actual_type->data.pointer.child_type; |
| | 12703 | bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 |
| | 12704 | || !actual_type->data.pointer.is_const); |
| | 12705 | if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type, |
| | 12706 | array_type->data.array.child_type, source_node, |
| | 12707 | !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk) |
| | 12708 | { |
| | 12709 | // If the pointers both have ABI align, it works. |
| | 12710 | // Or if the array length is 0, alignment doesn't matter. |
| | 12711 | bool ok_align = array_type->data.array.len == 0 || |
| | 12712 | (slice_ptr_type->data.pointer.explicit_alignment == 0 && |
| | 12713 | actual_type->data.pointer.explicit_alignment == 0); |
| | 12714 | if (!ok_align) { |
| | 12715 | // If either one has non ABI align, we have to resolve them both |
| | 12716 | if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, |
| | 12717 | ResolveStatusAlignmentKnown))) |
| | 12718 | { |
| | 12719 | return ira->codegen->invalid_instruction; |
| | 12720 | } |
| | 12721 | if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, |
| | 12722 | ResolveStatusAlignmentKnown))) |
| | 12723 | { |
| | 12724 | return ira->codegen->invalid_instruction; |
| | 12725 | } |
| | 12726 | ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); |
| | 12727 | } |
| | 12728 | if (ok_align) { |
| | 12729 | if (wanted_type->id == ZigTypeIdErrorUnion) { |
| | 12730 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value, nullptr); |
| | 12731 | if (type_is_invalid(cast1->value.type)) |
| | 12732 | return ira->codegen->invalid_instruction; |
| | 12733 | |
| | 12734 | IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc); |
| | 12735 | if (type_is_invalid(cast2->value.type)) |
| | 12736 | return ira->codegen->invalid_instruction; |
| | 12737 | |
| | 12738 | return cast2; |
| | 12739 | } else { |
| | 12740 | return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); |
| | 12741 | } |
| | 12742 | } |
| | 12743 | } |
| | 12744 | } |
| | 12745 | |
| | 12746 | // *[N]T to E![]T |
| | 12747 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| | 12748 | is_slice(wanted_type->data.error_union.payload_type) && |
| 12646 | actual_type->id == ZigTypeIdPointer && | 12749 | actual_type->id == ZigTypeIdPointer && |
| 12647 | actual_type->data.pointer.ptr_len == PtrLenSingle && | 12750 | actual_type->data.pointer.ptr_len == PtrLenSingle && |
| 12648 | actual_type->data.pointer.child_type->id == ZigTypeIdArray) | 12751 | actual_type->data.pointer.child_type->id == ZigTypeIdArray) |
| 12649 | { | 12752 | { |
| 12650 | ZigType *slice_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; | 12753 | ZigType *slice_type = wanted_type->data.error_union.payload_type; |
| | 12754 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; |
| 12651 | assert(slice_ptr_type->id == ZigTypeIdPointer); | 12755 | assert(slice_ptr_type->id == ZigTypeIdPointer); |
| 12652 | ZigType *array_type = actual_type->data.pointer.child_type; | 12756 | ZigType *array_type = actual_type->data.pointer.child_type; |
| 12653 | bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 | 12757 | bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 |
| ... | @@ -12674,7 +12778,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -12674,7 +12778,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 12674 | ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); | 12778 | ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); |
| 12675 | } | 12779 | } |
| 12676 | if (ok_align) { | 12780 | if (ok_align) { |
| 12677 | return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc); | 12781 | return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); |
| 12678 | } | 12782 | } |
| 12679 | } | 12783 | } |
| 12680 | } | 12784 | } |