| ... | ... | @@ -10494,6 +10494,50 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10494 | 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 | 10541 | if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) && |
| 10498 | 10542 | (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || |
| 10499 | 10543 | cur_type->data.array.len == 0) && |
| ... | ... | @@ -10505,6 +10549,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10505 | 10549 | continue; |
| 10506 | 10550 | } |
| 10507 | 10551 | |
| 10552 | // [N]T to []T |
| 10508 | 10553 | if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && |
| 10509 | 10554 | (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || |
| 10510 | 10555 | prev_type->data.array.len == 0) && |
| ... | ... | @@ -12642,12 +12687,71 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 12642 | 12687 | } |
| 12643 | 12688 | |
| 12644 | 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 | 12749 | actual_type->id == ZigTypeIdPointer && |
| 12647 | 12750 | actual_type->data.pointer.ptr_len == PtrLenSingle && |
| 12648 | 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 | 12755 | assert(slice_ptr_type->id == ZigTypeIdPointer); |
| 12652 | 12756 | ZigType *array_type = actual_type->data.pointer.child_type; |
| 12653 | 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 | 12778 | ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); |
| 12675 | 12779 | } |
| 12676 | 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 | } |