| ... | ... | @@ -15573,6 +15573,110 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15573 | 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 | 15680 | static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 15577 | 15681 | IrInstruction *op1 = instruction->op1->child; |
| 15578 | 15682 | ZigType *op1_type = op1->value->type; |
| ... | ... | @@ -15584,6 +15688,10 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 15584 | 15688 | if (type_is_invalid(op2_type)) |
| 15585 | 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 | 15695 | ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); |
| 15588 | 15696 | if (!op1_val) |
| 15589 | 15697 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -17446,11 +17554,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 17446 | 17554 | } |
| 17447 | 17555 | |
| 17448 | 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 | 17558 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 17451 | 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 | 17563 | ptr->value->data.x_ptr.mut == ConstPtrMutInfer) |
| 17455 | 17564 | { |
| 17456 | 17565 | if (instr_is_comptime(value)) { |