| ... | @@ -15573,6 +15573,110 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15573,6 +15573,110 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15573 | return result; | 15573 | return result; |
| 15574 | } | 15574 | } |
| 15575 | | 15575 | |
| | 15576 | static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source_instr, |
| | 15577 | IrInstruction *op1, IrInstruction *op2) |
| | 15578 | { |
| | 15579 | Error err; |
| | 15580 | ZigType *op1_type = op1->value->type; |
| | 15581 | ZigType *op2_type = op2->value->type; |
| | 15582 | |
| | 15583 | uint32_t op1_field_count = op1_type->data.structure.src_field_count; |
| | 15584 | uint32_t op2_field_count = op2_type->data.structure.src_field_count; |
| | 15585 | |
| | 15586 | Buf *bare_name = buf_alloc(); |
| | 15587 | Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct), |
| | 15588 | source_instr->scope, source_instr->source_node, bare_name); |
| | 15589 | ZigType *new_type = get_partial_container_type(ira->codegen, source_instr->scope, |
| | 15590 | ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto); |
| | 15591 | new_type->data.structure.special = StructSpecialInferredTuple; |
| | 15592 | new_type->data.structure.resolve_status = ResolveStatusBeingInferred; |
| | 15593 | |
| | 15594 | bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instr->scope); |
| | 15595 | |
| | 15596 | IrInstruction *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), |
| | 15597 | new_type, nullptr, false, false, true); |
| | 15598 | uint32_t new_field_count = op1_field_count + op2_field_count; |
| | 15599 | |
| | 15600 | new_type->data.structure.src_field_count = new_field_count; |
| | 15601 | new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields, |
| | 15602 | 0, new_field_count); |
| | 15603 | for (uint32_t i = 0; i < new_field_count; i += 1) { |
| | 15604 | TypeStructField *src_field; |
| | 15605 | if (i < op1_field_count) { |
| | 15606 | src_field = op1_type->data.structure.fields[i]; |
| | 15607 | } else { |
| | 15608 | src_field = op2_type->data.structure.fields[i - op1_field_count]; |
| | 15609 | } |
| | 15610 | TypeStructField *new_field = new_type->data.structure.fields[i]; |
| | 15611 | new_field->name = buf_sprintf("%" PRIu32, i); |
| | 15612 | new_field->type_entry = src_field->type_entry; |
| | 15613 | new_field->type_val = src_field->type_val; |
| | 15614 | new_field->src_index = i; |
| | 15615 | new_field->decl_node = src_field->decl_node; |
| | 15616 | new_field->init_val = src_field->init_val; |
| | 15617 | new_field->is_comptime = src_field->is_comptime; |
| | 15618 | } |
| | 15619 | if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown))) |
| | 15620 | return ira->codegen->invalid_instruction; |
| | 15621 | |
| | 15622 | ZigList<IrInstruction *> const_ptrs = {}; |
| | 15623 | IrInstruction *first_non_const_instruction = nullptr; |
| | 15624 | for (uint32_t i = 0; i < new_field_count; i += 1) { |
| | 15625 | TypeStructField *dst_field = new_type->data.structure.fields[i]; |
| | 15626 | IrInstruction *src_struct_op; |
| | 15627 | TypeStructField *src_field; |
| | 15628 | if (i < op1_field_count) { |
| | 15629 | src_field = op1_type->data.structure.fields[i]; |
| | 15630 | src_struct_op = op1; |
| | 15631 | } else { |
| | 15632 | src_field = op2_type->data.structure.fields[i - op1_field_count]; |
| | 15633 | src_struct_op = op2; |
| | 15634 | } |
| | 15635 | IrInstruction *field_value = ir_analyze_struct_value_field_value(ira, source_instr, |
| | 15636 | src_struct_op, src_field); |
| | 15637 | if (type_is_invalid(field_value->value->type)) |
| | 15638 | return ira->codegen->invalid_instruction; |
| | 15639 | IrInstruction *dest_ptr = ir_analyze_struct_field_ptr(ira, source_instr, dst_field, |
| | 15640 | new_struct_ptr, new_type, true); |
| | 15641 | if (type_is_invalid(dest_ptr->value->type)) |
| | 15642 | return ira->codegen->invalid_instruction; |
| | 15643 | if (instr_is_comptime(field_value)) { |
| | 15644 | const_ptrs.append(dest_ptr); |
| | 15645 | } else { |
| | 15646 | first_non_const_instruction = field_value; |
| | 15647 | } |
| | 15648 | IrInstruction *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value, |
| | 15649 | true); |
| | 15650 | if (type_is_invalid(store_ptr_inst->value->type)) |
| | 15651 | return ira->codegen->invalid_instruction; |
| | 15652 | } |
| | 15653 | if (const_ptrs.length != new_field_count) { |
| | 15654 | new_struct_ptr->value->special = ConstValSpecialRuntime; |
| | 15655 | for (size_t i = 0; i < const_ptrs.length; i += 1) { |
| | 15656 | IrInstruction *elem_result_loc = const_ptrs.at(i); |
| | 15657 | assert(elem_result_loc->value->special == ConstValSpecialStatic); |
| | 15658 | if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) { |
| | 15659 | // This field will be generated comptime; no need to do this. |
| | 15660 | continue; |
| | 15661 | } |
| | 15662 | IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); |
| | 15663 | elem_result_loc->value->special = ConstValSpecialRuntime; |
| | 15664 | ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false); |
| | 15665 | } |
| | 15666 | } |
| | 15667 | IrInstruction *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); |
| | 15668 | if (instr_is_comptime(result)) |
| | 15669 | return result; |
| | 15670 | |
| | 15671 | if (is_comptime) { |
| | 15672 | ir_add_error_node(ira, first_non_const_instruction->source_node, |
| | 15673 | buf_sprintf("unable to evaluate constant expression")); |
| | 15674 | return ira->codegen->invalid_instruction; |
| | 15675 | } |
| | 15676 | |
| | 15677 | return result; |
| | 15678 | } |
| | 15679 | |
| 15576 | static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 15680 | static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 15577 | IrInstruction *op1 = instruction->op1->child; | 15681 | IrInstruction *op1 = instruction->op1->child; |
| 15578 | ZigType *op1_type = op1->value->type; | 15682 | ZigType *op1_type = op1->value->type; |
| ... | @@ -15584,6 +15688,10 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -15584,6 +15688,10 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 15584 | if (type_is_invalid(op2_type)) | 15688 | if (type_is_invalid(op2_type)) |
| 15585 | return ira->codegen->invalid_instruction; | 15689 | return ira->codegen->invalid_instruction; |
| 15586 | | 15690 | |
| | 15691 | if (is_tuple(op1_type) && is_tuple(op2_type)) { |
| | 15692 | return ir_analyze_tuple_cat(ira, &instruction->base, op1, op2); |
| | 15693 | } |
| | 15694 | |
| 15587 | ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); | 15695 | ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); |
| 15588 | if (!op1_val) | 15696 | if (!op1_val) |
| 15589 | return ira->codegen->invalid_instruction; | 15697 | return ira->codegen->invalid_instruction; |
| ... | @@ -17446,11 +17554,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source | ... | @@ -17446,11 +17554,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 17446 | } | 17554 | } |
| 17447 | | 17555 | |
| 17448 | if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 17556 | if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 17449 | if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) { | 17557 | if (!allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) { |
| 17450 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | 17558 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 17451 | return ira->codegen->invalid_instruction; | 17559 | return ira->codegen->invalid_instruction; |
| 17452 | } | 17560 | } |
| 17453 | if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar || | 17561 | if ((allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) || |
| | 17562 | ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar || |
| 17454 | ptr->value->data.x_ptr.mut == ConstPtrMutInfer) | 17563 | ptr->value->data.x_ptr.mut == ConstPtrMutInfer) |
| 17455 | { | 17564 | { |
| 17456 | if (instr_is_comptime(value)) { | 17565 | if (instr_is_comptime(value)) { |