| ... | ... | @@ -17351,14 +17351,15 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, |
| 17351 | 17351 | ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto); |
| 17352 | 17352 | new_type->data.structure.special = StructSpecialInferredTuple; |
| 17353 | 17353 | new_type->data.structure.resolve_status = ResolveStatusBeingInferred; |
| 17354 | | |
| 17355 | | IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), |
| 17356 | | new_type, nullptr, false, true); |
| 17357 | 17354 | uint32_t new_field_count = op1_field_count + op2_field_count; |
| 17358 | 17355 | |
| 17359 | 17356 | new_type->data.structure.src_field_count = new_field_count; |
| 17360 | 17357 | new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields, |
| 17361 | 17358 | 0, new_field_count); |
| 17359 | |
| 17360 | IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), |
| 17361 | new_type, nullptr, false, true); |
| 17362 | |
| 17362 | 17363 | for (uint32_t i = 0; i < new_field_count; i += 1) { |
| 17363 | 17364 | TypeStructField *src_field; |
| 17364 | 17365 | if (i < op1_field_count) { |
| ... | ... | @@ -17422,8 +17423,10 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, |
| 17422 | 17423 | ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, true); |
| 17423 | 17424 | } |
| 17424 | 17425 | } |
| 17425 | | IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); |
| 17426 | | return result; |
| 17426 | |
| 17427 | const_ptrs.deinit(); |
| 17428 | |
| 17429 | return ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); |
| 17427 | 17430 | } |
| 17428 | 17431 | |
| 17429 | 17432 | static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instruction) { |
| ... | ... | @@ -17480,8 +17483,9 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi |
| 17480 | 17483 | ZigValue *len_val = op1_val->data.x_struct.fields[slice_len_index]; |
| 17481 | 17484 | op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint); |
| 17482 | 17485 | sentinel1 = ptr_type->data.pointer.sentinel; |
| 17483 | | } else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle && |
| 17484 | | op1_type->data.pointer.child_type->id == ZigTypeIdArray) |
| 17486 | } else if (op1_type->id == ZigTypeIdPointer && |
| 17487 | op1_type->data.pointer.ptr_len == PtrLenSingle && |
| 17488 | op1_type->data.pointer.child_type->id == ZigTypeIdArray) |
| 17485 | 17489 | { |
| 17486 | 17490 | ZigType *array_type = op1_type->data.pointer.child_type; |
| 17487 | 17491 | child_type = array_type->data.array.child_type; |
| ... | ... | @@ -17654,6 +17658,103 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi |
| 17654 | 17658 | return result; |
| 17655 | 17659 | } |
| 17656 | 17660 | |
| 17661 | static IrInstGen *ir_analyze_tuple_mult(IrAnalyze *ira, IrInst* source_instr, |
| 17662 | IrInstGen *op1, IrInstGen *op2) |
| 17663 | { |
| 17664 | Error err; |
| 17665 | ZigType *op1_type = op1->value->type; |
| 17666 | uint64_t op1_field_count = op1_type->data.structure.src_field_count; |
| 17667 | |
| 17668 | uint64_t mult_amt; |
| 17669 | if (!ir_resolve_usize(ira, op2, &mult_amt)) |
| 17670 | return ira->codegen->invalid_inst_gen; |
| 17671 | |
| 17672 | uint64_t new_field_count; |
| 17673 | if (mul_u64_overflow(op1_field_count, mult_amt, &new_field_count)) { |
| 17674 | ir_add_error(ira, source_instr, buf_sprintf("operation results in overflow")); |
| 17675 | return ira->codegen->invalid_inst_gen; |
| 17676 | } |
| 17677 | |
| 17678 | Buf *bare_name = buf_alloc(); |
| 17679 | Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct), |
| 17680 | source_instr->scope, source_instr->source_node, bare_name); |
| 17681 | ZigType *new_type = get_partial_container_type(ira->codegen, source_instr->scope, |
| 17682 | ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto); |
| 17683 | new_type->data.structure.special = StructSpecialInferredTuple; |
| 17684 | new_type->data.structure.resolve_status = ResolveStatusBeingInferred; |
| 17685 | new_type->data.structure.src_field_count = new_field_count; |
| 17686 | new_type->data.structure.fields = realloc_type_struct_fields( |
| 17687 | new_type->data.structure.fields, 0, new_field_count); |
| 17688 | |
| 17689 | IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), |
| 17690 | new_type, nullptr, false, true); |
| 17691 | |
| 17692 | for (uint64_t i = 0; i < new_field_count; i += 1) { |
| 17693 | TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count]; |
| 17694 | TypeStructField *new_field = new_type->data.structure.fields[i]; |
| 17695 | |
| 17696 | new_field->name = buf_sprintf("%lu", i); |
| 17697 | new_field->type_entry = src_field->type_entry; |
| 17698 | new_field->type_val = src_field->type_val; |
| 17699 | new_field->src_index = i; |
| 17700 | new_field->decl_node = src_field->decl_node; |
| 17701 | new_field->init_val = src_field->init_val; |
| 17702 | new_field->is_comptime = src_field->is_comptime; |
| 17703 | } |
| 17704 | |
| 17705 | if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown))) |
| 17706 | return ira->codegen->invalid_inst_gen; |
| 17707 | |
| 17708 | ZigList<IrInstGen *> const_ptrs = {}; |
| 17709 | for (uint64_t i = 0; i < new_field_count; i += 1) { |
| 17710 | TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count]; |
| 17711 | TypeStructField *dst_field = new_type->data.structure.fields[i]; |
| 17712 | |
| 17713 | IrInstGen *field_value = ir_analyze_struct_value_field_value( |
| 17714 | ira, source_instr, op1, src_field); |
| 17715 | if (type_is_invalid(field_value->value->type)) |
| 17716 | return ira->codegen->invalid_inst_gen; |
| 17717 | |
| 17718 | IrInstGen *dest_ptr = ir_analyze_struct_field_ptr( |
| 17719 | ira, source_instr, dst_field, new_struct_ptr, new_type, true); |
| 17720 | if (type_is_invalid(dest_ptr->value->type)) |
| 17721 | return ira->codegen->invalid_inst_gen; |
| 17722 | |
| 17723 | if (instr_is_comptime(field_value)) { |
| 17724 | const_ptrs.append(dest_ptr); |
| 17725 | } |
| 17726 | |
| 17727 | IrInstGen *store_ptr_inst = ir_analyze_store_ptr( |
| 17728 | ira, source_instr, dest_ptr, field_value, true); |
| 17729 | if (type_is_invalid(store_ptr_inst->value->type)) |
| 17730 | return ira->codegen->invalid_inst_gen; |
| 17731 | } |
| 17732 | |
| 17733 | if (const_ptrs.length != new_field_count) { |
| 17734 | new_struct_ptr->value->special = ConstValSpecialRuntime; |
| 17735 | for (size_t i = 0; i < const_ptrs.length; i += 1) { |
| 17736 | IrInstGen *elem_result_loc = const_ptrs.at(i); |
| 17737 | assert(elem_result_loc->value->special == ConstValSpecialStatic); |
| 17738 | if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) { |
| 17739 | // This field will be generated comptime; no need to do this. |
| 17740 | continue; |
| 17741 | } |
| 17742 | IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr); |
| 17743 | if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) { |
| 17744 | elem_result_loc->value->special = ConstValSpecialRuntime; |
| 17745 | } |
| 17746 | IrInstGen *store_ptr_inst = ir_analyze_store_ptr( |
| 17747 | ira, &elem_result_loc->base, elem_result_loc, deref, true); |
| 17748 | if (type_is_invalid(store_ptr_inst->value->type)) |
| 17749 | return ira->codegen->invalid_inst_gen; |
| 17750 | } |
| 17751 | } |
| 17752 | |
| 17753 | const_ptrs.deinit(); |
| 17754 | |
| 17755 | return ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); |
| 17756 | } |
| 17757 | |
| 17657 | 17758 | static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruction) { |
| 17658 | 17759 | IrInstGen *op1 = instruction->op1->child; |
| 17659 | 17760 | if (type_is_invalid(op1->value->type)) |
| ... | ... | @@ -17671,8 +17772,9 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct |
| 17671 | 17772 | array_val = ir_resolve_const(ira, op1, UndefOk); |
| 17672 | 17773 | if (array_val == nullptr) |
| 17673 | 17774 | return ira->codegen->invalid_inst_gen; |
| 17674 | | } else if (op1->value->type->id == ZigTypeIdPointer && op1->value->type->data.pointer.ptr_len == PtrLenSingle && |
| 17675 | | op1->value->type->data.pointer.child_type->id == ZigTypeIdArray) |
| 17775 | } else if (op1->value->type->id == ZigTypeIdPointer && |
| 17776 | op1->value->type->data.pointer.ptr_len == PtrLenSingle && |
| 17777 | op1->value->type->data.pointer.child_type->id == ZigTypeIdArray) |
| 17676 | 17778 | { |
| 17677 | 17779 | array_type = op1->value->type->data.pointer.child_type; |
| 17678 | 17780 | IrInstGen *array_inst = ir_get_deref(ira, &op1->base, op1, nullptr); |
| ... | ... | @@ -17682,6 +17784,8 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct |
| 17682 | 17784 | if (array_val == nullptr) |
| 17683 | 17785 | return ira->codegen->invalid_inst_gen; |
| 17684 | 17786 | want_ptr_to_array = true; |
| 17787 | } else if (is_tuple(op1->value->type)) { |
| 17788 | return ir_analyze_tuple_mult(ira, &instruction->base.base, op1, op2); |
| 17685 | 17789 | } else { |
| 17686 | 17790 | ir_add_error(ira, &op1->base, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name))); |
| 17687 | 17791 | return ira->codegen->invalid_inst_gen; |