| ... | ... | @@ -12693,34 +12693,50 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc |
| 12693 | 12693 | assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray); |
| 12694 | 12694 | |
| 12695 | 12695 | ZigType *array_type = array_ptr->value->type->data.pointer.child_type; |
| 12696 | | const size_t array_len = array_type->data.array.len; |
| 12696 | size_t array_len = array_type->data.array.len; |
| 12697 | 12697 | |
| 12698 | 12698 | // A zero-sized array can be casted regardless of the destination alignment, or |
| 12699 | 12699 | // whether the pointer is undefined, and the result is always comptime known. |
| 12700 | | if (array_len == 0) { |
| 12701 | | ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>(); |
| 12702 | | undef_array->special = ConstValSpecialUndef; |
| 12703 | | undef_array->type = array_type; |
| 12704 | | |
| 12705 | | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 12706 | | init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false); |
| 12707 | | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 12708 | | result->value->type = wanted_type; |
| 12709 | | return result; |
| 12710 | | } |
| 12700 | // TODO However, this is exposing a result location bug that I failed to solve on the first try. |
| 12701 | // If you want to try to fix the bug, uncomment this block and get the tests passing. |
| 12702 | //if (array_len == 0 && array_type->data.array.sentinel == nullptr) { |
| 12703 | // ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>(); |
| 12704 | // undef_array->special = ConstValSpecialUndef; |
| 12705 | // undef_array->type = array_type; |
| 12706 | |
| 12707 | // IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 12708 | // init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false); |
| 12709 | // result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 12710 | // result->value->type = wanted_type; |
| 12711 | // return result; |
| 12712 | //} |
| 12711 | 12713 | |
| 12712 | 12714 | if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) { |
| 12713 | 12715 | return ira->codegen->invalid_inst_gen; |
| 12714 | 12716 | } |
| 12715 | 12717 | |
| 12716 | | wanted_type = adjust_slice_align(ira->codegen, wanted_type, |
| 12717 | | get_ptr_align(ira->codegen, array_ptr->value->type)); |
| 12718 | if (array_len != 0) { |
| 12719 | wanted_type = adjust_slice_align(ira->codegen, wanted_type, |
| 12720 | get_ptr_align(ira->codegen, array_ptr->value->type)); |
| 12721 | } |
| 12718 | 12722 | |
| 12719 | 12723 | if (instr_is_comptime(array_ptr)) { |
| 12720 | | ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); |
| 12724 | UndefAllowed undef_allowed = (array_len == 0) ? UndefOk : UndefBad; |
| 12725 | ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, undef_allowed); |
| 12721 | 12726 | if (array_ptr_val == nullptr) |
| 12722 | 12727 | return ira->codegen->invalid_inst_gen; |
| 12723 | 12728 | ir_assert(is_slice(wanted_type), source_instr); |
| 12729 | if (array_ptr_val->special == ConstValSpecialUndef) { |
| 12730 | ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>(); |
| 12731 | undef_array->special = ConstValSpecialUndef; |
| 12732 | undef_array->type = array_type; |
| 12733 | |
| 12734 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 12735 | init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false); |
| 12736 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 12737 | result->value->type = wanted_type; |
| 12738 | return result; |
| 12739 | } |
| 12724 | 12740 | bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; |
| 12725 | 12741 | // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee |
| 12726 | 12742 | if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) { |
| ... | ... | @@ -26314,18 +26330,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26314 | 26330 | // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these |
| 26315 | 26331 | // values by making the return type a slice. |
| 26316 | 26332 | ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc); |
| 26317 | | |
| 26318 | | if ((res_loc_type == nullptr || !is_slice(res_loc_type)) && |
| 26319 | | value_is_comptime(casted_start->value) && |
| 26333 | bool result_loc_is_slice = (res_loc_type != nullptr && is_slice(res_loc_type)); |
| 26334 | bool end_is_known = !result_loc_is_slice && |
| 26320 | 26335 | ((end != nullptr && value_is_comptime(end->value)) || |
| 26321 | | (end == nullptr && child_array_type->id == ZigTypeIdArray))) |
| 26322 | | { |
| 26323 | | ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); |
| 26324 | | if (!start_val) |
| 26325 | | return ira->codegen->invalid_inst_gen; |
| 26326 | | |
| 26327 | | uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint); |
| 26336 | (end == nullptr && child_array_type->id == ZigTypeIdArray)); |
| 26328 | 26337 | |
| 26338 | ZigValue *array_sentinel = sentinel_val; |
| 26339 | if (end_is_known) { |
| 26329 | 26340 | uint64_t end_scalar; |
| 26330 | 26341 | if (end != nullptr) { |
| 26331 | 26342 | ZigValue *end_val = ir_resolve_const(ira, end, UndefBad); |
| ... | ... | @@ -26335,36 +26346,46 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26335 | 26346 | } else { |
| 26336 | 26347 | end_scalar = child_array_type->data.array.len; |
| 26337 | 26348 | } |
| 26338 | | ZigValue *array_sentinel = (child_array_type->id == ZigTypeIdArray && |
| 26339 | | end_scalar == child_array_type->data.array.len) |
| 26340 | | ? child_array_type->data.array.sentinel : nullptr; |
| 26349 | array_sentinel = (child_array_type->id == ZigTypeIdArray && end_scalar == child_array_type->data.array.len) |
| 26350 | ? child_array_type->data.array.sentinel : sentinel_val; |
| 26341 | 26351 | |
| 26342 | | if (start_scalar > end_scalar) { |
| 26343 | | ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice")); |
| 26344 | | return ira->codegen->invalid_inst_gen; |
| 26345 | | } |
| 26352 | if (value_is_comptime(casted_start->value)) { |
| 26353 | ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); |
| 26354 | if (!start_val) |
| 26355 | return ira->codegen->invalid_inst_gen; |
| 26346 | 26356 | |
| 26347 | | uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment; |
| 26348 | | uint32_t ptr_byte_alignment = 0; |
| 26349 | | if (end_scalar > start_scalar) { |
| 26350 | | if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment))) |
| 26357 | uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint); |
| 26358 | |
| 26359 | if (start_scalar > end_scalar) { |
| 26360 | ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice")); |
| 26351 | 26361 | return ira->codegen->invalid_inst_gen; |
| 26352 | | } |
| 26362 | } |
| 26363 | |
| 26364 | uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment; |
| 26365 | uint32_t ptr_byte_alignment = 0; |
| 26366 | if (end_scalar > start_scalar) { |
| 26367 | if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment))) |
| 26368 | return ira->codegen->invalid_inst_gen; |
| 26369 | } |
| 26353 | 26370 | |
| 26354 | | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, |
| 26355 | | array_sentinel); |
| 26356 | | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, |
| 26357 | | non_sentinel_slice_ptr_type->data.pointer.is_const, |
| 26358 | | non_sentinel_slice_ptr_type->data.pointer.is_volatile, |
| 26359 | | PtrLenSingle, ptr_byte_alignment, 0, 0, false); |
| 26360 | | } else if (sentinel_val != nullptr) { |
| 26371 | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, |
| 26372 | array_sentinel); |
| 26373 | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, |
| 26374 | non_sentinel_slice_ptr_type->data.pointer.is_const, |
| 26375 | non_sentinel_slice_ptr_type->data.pointer.is_volatile, |
| 26376 | PtrLenSingle, ptr_byte_alignment, 0, 0, false); |
| 26377 | goto done_with_return_type; |
| 26378 | } |
| 26379 | } |
| 26380 | if (array_sentinel != nullptr) { |
| 26361 | 26381 | // TODO deal with non-abi-alignment here |
| 26362 | | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); |
| 26382 | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, array_sentinel); |
| 26363 | 26383 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 26364 | 26384 | } else { |
| 26365 | 26385 | // TODO deal with non-abi-alignment here |
| 26366 | 26386 | return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type); |
| 26367 | 26387 | } |
| 26388 | done_with_return_type: |
| 26368 | 26389 | |
| 26369 | 26390 | if (instr_is_comptime(ptr_ptr) && |
| 26370 | 26391 | value_is_comptime(casted_start->value) && |