| ... | ... | @@ -8404,7 +8404,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8404 | 8404 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) |
| 8405 | 8405 | return ira->codegen->invalid_instruction; |
| 8406 | 8406 | uint64_t child_type_size = type_size(ira->codegen, |
| 8407 | | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type); |
| 8407 | wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type); |
| 8408 | 8408 | if (actual_type->data.array.len % child_type_size == 0) { |
| 8409 | 8409 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBytesToSlice, true); |
| 8410 | 8410 | } else { |
| ... | ... | @@ -10870,6 +10870,15 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 10870 | 10870 | var_ptr_instruction->is_volatile); |
| 10871 | 10871 | } |
| 10872 | 10872 | |
| 10873 | static TypeTableEntry *adjust_ptr_align(CodeGen *g, TypeTableEntry *ptr_type, uint32_t new_align) { |
| 10874 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 10875 | return get_pointer_to_type_extra(g, |
| 10876 | ptr_type->data.pointer.child_type, |
| 10877 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 10878 | new_align, |
| 10879 | ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); |
| 10880 | } |
| 10881 | |
| 10873 | 10882 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| 10874 | 10883 | IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other; |
| 10875 | 10884 | if (type_is_invalid(array_ptr->value.type)) |
| ... | ... | @@ -10888,6 +10897,9 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10888 | 10897 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 10889 | 10898 | |
| 10890 | 10899 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; |
| 10900 | |
| 10901 | // At first return_type will be the pointer type we want to return, except with an optimistic alignment. |
| 10902 | // We will adjust return_type's alignment before returning it. |
| 10891 | 10903 | TypeTableEntry *return_type; |
| 10892 | 10904 | |
| 10893 | 10905 | if (type_is_invalid(array_type)) { |
| ... | ... | @@ -10918,7 +10930,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10918 | 10930 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 10919 | 10931 | return_type = array_type; |
| 10920 | 10932 | } else if (is_slice(array_type)) { |
| 10921 | | return_type = array_type->data.structure.fields[0].type_entry; |
| 10933 | return_type = array_type->data.structure.fields[slice_ptr_index].type_entry; |
| 10922 | 10934 | } else if (array_type->id == TypeTableEntryIdArgTuple) { |
| 10923 | 10935 | ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); |
| 10924 | 10936 | if (!ptr_val) |
| ... | ... | @@ -10961,6 +10973,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10961 | 10973 | return ira->codegen->builtin_types.entry_invalid; |
| 10962 | 10974 | |
| 10963 | 10975 | bool safety_check_on = elem_ptr_instruction->safety_check_on; |
| 10976 | ensure_complete_type(ira->codegen, return_type->data.pointer.child_type); |
| 10977 | uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); |
| 10978 | uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); |
| 10979 | uint64_t ptr_align = return_type->data.pointer.alignment; |
| 10964 | 10980 | if (instr_is_comptime(casted_elem_index)) { |
| 10965 | 10981 | uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint); |
| 10966 | 10982 | if (array_type->id == TypeTableEntryIdArray) { |
| ... | ... | @@ -10974,6 +10990,26 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10974 | 10990 | safety_check_on = false; |
| 10975 | 10991 | } |
| 10976 | 10992 | |
| 10993 | { |
| 10994 | // figure out the largest alignment possible |
| 10995 | uint64_t chosen_align = abi_align; |
| 10996 | if (ptr_align >= abi_align) { |
| 10997 | while (ptr_align > abi_align) { |
| 10998 | if ((index * elem_size) % ptr_align == 0) { |
| 10999 | chosen_align = ptr_align; |
| 11000 | break; |
| 11001 | } |
| 11002 | ptr_align >>= 1; |
| 11003 | } |
| 11004 | } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) { |
| 11005 | chosen_align = ptr_align; |
| 11006 | } else { |
| 11007 | // can't get here because guaranteed elem_size >= abi_align |
| 11008 | zig_unreachable(); |
| 11009 | } |
| 11010 | return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align); |
| 11011 | } |
| 11012 | |
| 10977 | 11013 | ConstExprValue *array_ptr_val; |
| 10978 | 11014 | if (array_ptr->value.special != ConstValSpecialRuntime && |
| 10979 | 11015 | (array_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) && |
| ... | ... | @@ -11085,6 +11121,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 11085 | 11121 | } |
| 11086 | 11122 | } |
| 11087 | 11123 | |
| 11124 | } else { |
| 11125 | // runtime known element index |
| 11126 | if (ptr_align < abi_align) { |
| 11127 | if (elem_size >= ptr_align && elem_size % ptr_align == 0) { |
| 11128 | return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align); |
| 11129 | } else { |
| 11130 | // can't get here because guaranteed elem_size >= abi_align |
| 11131 | zig_unreachable(); |
| 11132 | } |
| 11133 | } else { |
| 11134 | return_type = adjust_ptr_align(ira->codegen, return_type, abi_align); |
| 11135 | } |
| 11088 | 11136 | } |
| 11089 | 11137 | |
| 11090 | 11138 | ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr, |
| ... | ... | @@ -14520,11 +14568,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 14520 | 14568 | uint32_t old_align_bytes; |
| 14521 | 14569 | |
| 14522 | 14570 | if (target_type->id == TypeTableEntryIdPointer) { |
| 14523 | | result_type = get_pointer_to_type_extra(ira->codegen, |
| 14524 | | target_type->data.pointer.child_type, |
| 14525 | | target_type->data.pointer.is_const, target_type->data.pointer.is_volatile, |
| 14526 | | align_bytes, |
| 14527 | | target_type->data.pointer.bit_offset, target_type->data.pointer.unaligned_bit_count); |
| 14571 | result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes); |
| 14528 | 14572 | } else if (target_type->id == TypeTableEntryIdFn) { |
| 14529 | 14573 | FnTypeId fn_type_id = target_type->data.fn.fn_type_id; |
| 14530 | 14574 | old_align_bytes = fn_type_id.alignment; |
| ... | ... | @@ -14535,11 +14579,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 14535 | 14579 | { |
| 14536 | 14580 | TypeTableEntry *ptr_type = target_type->data.maybe.child_type; |
| 14537 | 14581 | old_align_bytes = ptr_type->data.pointer.alignment; |
| 14538 | | TypeTableEntry *better_ptr_type = get_pointer_to_type_extra(ira->codegen, |
| 14539 | | ptr_type->data.pointer.child_type, |
| 14540 | | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14541 | | align_bytes, |
| 14542 | | ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); |
| 14582 | TypeTableEntry *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes); |
| 14543 | 14583 | |
| 14544 | 14584 | result_type = get_maybe_type(ira->codegen, better_ptr_type); |
| 14545 | 14585 | } else if (target_type->id == TypeTableEntryIdMaybe && |
| ... | ... | @@ -14553,11 +14593,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 14553 | 14593 | } else if (is_slice(target_type)) { |
| 14554 | 14594 | TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry; |
| 14555 | 14595 | old_align_bytes = slice_ptr_type->data.pointer.alignment; |
| 14556 | | TypeTableEntry *result_ptr_type = get_pointer_to_type_extra(ira->codegen, |
| 14557 | | slice_ptr_type->data.pointer.child_type, |
| 14558 | | slice_ptr_type->data.pointer.is_const, slice_ptr_type->data.pointer.is_volatile, |
| 14559 | | align_bytes, |
| 14560 | | slice_ptr_type->data.pointer.bit_offset, slice_ptr_type->data.pointer.unaligned_bit_count); |
| 14596 | TypeTableEntry *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes); |
| 14561 | 14597 | result_type = get_slice_type(ira->codegen, result_ptr_type); |
| 14562 | 14598 | } else { |
| 14563 | 14599 | ir_add_error(ira, target, |