| ... | ... | @@ -20575,6 +20575,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_ |
| 20575 | 20575 | allow_zero); |
| 20576 | 20576 | } |
| 20577 | 20577 | |
| 20578 | static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align, |
| 20579 | uint64_t elem_index, uint32_t *result) |
| 20580 | { |
| 20581 | Error err; |
| 20582 | |
| 20583 | if (base_ptr_align == 0) { |
| 20584 | *result = 0; |
| 20585 | return ErrorNone; |
| 20586 | } |
| 20587 | |
| 20588 | // figure out the largest alignment possible |
| 20589 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) |
| 20590 | return err; |
| 20591 | |
| 20592 | uint64_t elem_size = type_size(ira->codegen, elem_type); |
| 20593 | uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type); |
| 20594 | uint64_t ptr_align = base_ptr_align; |
| 20595 | |
| 20596 | uint64_t chosen_align = abi_align; |
| 20597 | if (ptr_align >= abi_align) { |
| 20598 | while (ptr_align > abi_align) { |
| 20599 | if ((elem_index * elem_size) % ptr_align == 0) { |
| 20600 | chosen_align = ptr_align; |
| 20601 | break; |
| 20602 | } |
| 20603 | ptr_align >>= 1; |
| 20604 | } |
| 20605 | } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) { |
| 20606 | chosen_align = ptr_align; |
| 20607 | } else { |
| 20608 | // can't get here because guaranteed elem_size >= abi_align |
| 20609 | zig_unreachable(); |
| 20610 | } |
| 20611 | |
| 20612 | *result = chosen_align; |
| 20613 | return ErrorNone; |
| 20614 | } |
| 20615 | |
| 20578 | 20616 | static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) { |
| 20579 | 20617 | Error err; |
| 20580 | 20618 | IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child; |
| ... | ... | @@ -20713,29 +20751,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP |
| 20713 | 20751 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index, |
| 20714 | 20752 | nullptr, nullptr); |
| 20715 | 20753 | } else if (return_type->data.pointer.explicit_alignment != 0) { |
| 20716 | | // figure out the largest alignment possible |
| 20717 | | |
| 20718 | | if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) |
| 20754 | uint32_t chosen_align; |
| 20755 | if ((err = compute_elem_align(ira, return_type->data.pointer.child_type, |
| 20756 | return_type->data.pointer.explicit_alignment, index, &chosen_align))) |
| 20757 | { |
| 20719 | 20758 | return ira->codegen->invalid_inst_gen; |
| 20720 | | |
| 20721 | | uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); |
| 20722 | | uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); |
| 20723 | | uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); |
| 20724 | | |
| 20725 | | uint64_t chosen_align = abi_align; |
| 20726 | | if (ptr_align >= abi_align) { |
| 20727 | | while (ptr_align > abi_align) { |
| 20728 | | if ((index * elem_size) % ptr_align == 0) { |
| 20729 | | chosen_align = ptr_align; |
| 20730 | | break; |
| 20731 | | } |
| 20732 | | ptr_align >>= 1; |
| 20733 | | } |
| 20734 | | } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) { |
| 20735 | | chosen_align = ptr_align; |
| 20736 | | } else { |
| 20737 | | // can't get here because guaranteed elem_size >= abi_align |
| 20738 | | zig_unreachable(); |
| 20739 | 20759 | } |
| 20740 | 20760 | return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align); |
| 20741 | 20761 | } |
| ... | ... | @@ -26172,6 +26192,8 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy |
| 26172 | 26192 | } |
| 26173 | 26193 | |
| 26174 | 26194 | static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) { |
| 26195 | Error err; |
| 26196 | |
| 26175 | 26197 | IrInstGen *ptr_ptr = instruction->ptr->child; |
| 26176 | 26198 | if (type_is_invalid(ptr_ptr->value->type)) |
| 26177 | 26199 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -26307,10 +26329,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26307 | 26329 | return ira->codegen->invalid_inst_gen; |
| 26308 | 26330 | } |
| 26309 | 26331 | |
| 26310 | | // TODO in the case of non-zero start index, the byte alignment should be smarter here. |
| 26311 | | // we should be able to use the same logic as indexing. |
| 26312 | | uint32_t ptr_byte_alignment = ((end_scalar - start_scalar != 0) && start_scalar == 0) ? |
| 26313 | | non_sentinel_slice_ptr_type->data.pointer.explicit_alignment : 0; |
| 26332 | uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment; |
| 26333 | uint32_t ptr_byte_alignment = 0; |
| 26334 | if (end_scalar > start_scalar) { |
| 26335 | if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment))) |
| 26336 | return ira->codegen->invalid_inst_gen; |
| 26337 | } |
| 26338 | |
| 26314 | 26339 | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, |
| 26315 | 26340 | array_sentinel); |
| 26316 | 26341 | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, |
| ... | ... | @@ -26318,9 +26343,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26318 | 26343 | non_sentinel_slice_ptr_type->data.pointer.is_volatile, |
| 26319 | 26344 | PtrLenSingle, ptr_byte_alignment, 0, 0, false); |
| 26320 | 26345 | } else if (sentinel_val != nullptr) { |
| 26346 | // TODO deal with non-abi-alignment here |
| 26321 | 26347 | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); |
| 26322 | 26348 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 26323 | 26349 | } else { |
| 26350 | // TODO deal with non-abi-alignment here |
| 26324 | 26351 | return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type); |
| 26325 | 26352 | } |
| 26326 | 26353 | |