| ... | @@ -4711,109 +4711,120 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -4711,109 +4711,120 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 4711 | | 4711 | |
| 4712 | static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 4712 | static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 4713 | IrInstruction *op1 = instruction->op1->other; | 4713 | IrInstruction *op1 = instruction->op1->other; |
| 4714 | if (op1->type_entry->id == TypeTableEntryIdInvalid) | 4714 | TypeTableEntry *op1_canon_type = get_underlying_type(op1->type_entry); |
| | 4715 | if (op1_canon_type->id == TypeTableEntryIdInvalid) |
| 4715 | return ira->codegen->builtin_types.entry_invalid; | 4716 | return ira->codegen->builtin_types.entry_invalid; |
| 4716 | | 4717 | |
| 4717 | IrInstruction *op2 = instruction->op2->other; | 4718 | IrInstruction *op2 = instruction->op2->other; |
| 4718 | if (op2->type_entry->id == TypeTableEntryIdInvalid) | 4719 | TypeTableEntry *op2_canon_type = get_underlying_type(op2->type_entry); |
| | 4720 | if (op2_canon_type->id == TypeTableEntryIdInvalid) |
| 4719 | return ira->codegen->builtin_types.entry_invalid; | 4721 | return ira->codegen->builtin_types.entry_invalid; |
| 4720 | | 4722 | |
| 4721 | // AstNode **op1 = node->data.bin_op_expr.op1->parent_field; | 4723 | ConstExprValue *op1_val = ir_resolve_const(ira, op1); |
| 4722 | // AstNode **op2 = node->data.bin_op_expr.op2->parent_field; | 4724 | if (!op1_val) |
| 4723 | // | 4725 | return ira->codegen->builtin_types.entry_invalid; |
| 4724 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); | 4726 | |
| 4725 | // TypeTableEntry *child_type; | 4727 | ConstExprValue *op2_val = ir_resolve_const(ira, op2); |
| 4726 | // if (op1_type->id == TypeTableEntryIdInvalid) { | 4728 | if (!op2_val) |
| 4727 | // return g->builtin_types.entry_invalid; | 4729 | return ira->codegen->builtin_types.entry_invalid; |
| 4728 | // } else if (op1_type->id == TypeTableEntryIdArray) { | 4730 | |
| 4729 | // child_type = op1_type->data.array.child_type; | 4731 | ConstExprValue *op1_array_val; |
| 4730 | // } else if (op1_type->id == TypeTableEntryIdPointer && | 4732 | size_t op1_array_index; |
| 4731 | // op1_type->data.pointer.child_type == g->builtin_types.entry_u8) { | 4733 | size_t op1_array_end; |
| 4732 | // child_type = op1_type->data.pointer.child_type; | 4734 | TypeTableEntry *child_type; |
| 4733 | // } else { | 4735 | if (op1_canon_type->id == TypeTableEntryIdArray) { |
| 4734 | // add_node_error(g, *op1, buf_sprintf("expected array or C string literal, found '%s'", | 4736 | child_type = op1_canon_type->data.array.child_type; |
| 4735 | // buf_ptr(&op1_type->name))); | 4737 | op1_array_val = op1_val; |
| 4736 | // return g->builtin_types.entry_invalid; | 4738 | op1_array_index = 0; |
| 4737 | // } | 4739 | op1_array_end = op1_val->data.x_array.size; |
| 4738 | // | 4740 | } else if (op1_canon_type->id == TypeTableEntryIdPointer && |
| 4739 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); | 4741 | op1_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 && |
| 4740 | // | 4742 | op1_val->data.x_ptr.special == ConstPtrSpecialCStr) |
| 4741 | // if (op2_type->id == TypeTableEntryIdInvalid) { | 4743 | { |
| 4742 | // return g->builtin_types.entry_invalid; | 4744 | child_type = op1_canon_type->data.pointer.child_type; |
| 4743 | // } else if (op2_type->id == TypeTableEntryIdArray) { | 4745 | op1_array_val = op1_val->data.x_ptr.base_ptr; |
| 4744 | // if (op2_type->data.array.child_type != child_type) { | 4746 | op1_array_index = op1_val->data.x_ptr.index; |
| 4745 | // add_node_error(g, *op2, buf_sprintf("expected array of type '%s', found '%s'", | 4747 | op1_array_end = op1_array_val->data.x_array.size - 1; |
| 4746 | // buf_ptr(&child_type->name), | 4748 | } else { |
| 4747 | // buf_ptr(&op2_type->name))); | 4749 | ir_add_error(ira, op1, |
| 4748 | // return g->builtin_types.entry_invalid; | 4750 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->type_entry->name))); |
| 4749 | // } | 4751 | // TODO if meta_type is type decl, add note pointing to type decl declaration |
| 4750 | // } else if (op2_type->id == TypeTableEntryIdPointer && | 4752 | return ira->codegen->builtin_types.entry_invalid; |
| 4751 | // op2_type->data.pointer.child_type == g->builtin_types.entry_u8) { | 4753 | } |
| 4752 | // } else { | 4754 | |
| 4753 | // add_node_error(g, *op2, buf_sprintf("expected array or C string literal, found '%s'", | 4755 | ConstExprValue *op2_array_val; |
| 4754 | // buf_ptr(&op2_type->name))); | 4756 | size_t op2_array_index; |
| 4755 | // return g->builtin_types.entry_invalid; | 4757 | size_t op2_array_end; |
| 4756 | // } | 4758 | if (op2_canon_type->id == TypeTableEntryIdArray) { |
| 4757 | // | 4759 | if (op2_canon_type->data.array.child_type != child_type) { |
| 4758 | // ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; | 4760 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", |
| 4759 | // ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; | 4761 | buf_ptr(&child_type->name), |
| 4760 | // | 4762 | buf_ptr(&op2->type_entry->name))); |
| 4761 | // AstNode *bad_node; | 4763 | return ira->codegen->builtin_types.entry_invalid; |
| 4762 | // if (!op1_val->ok) { | 4764 | } |
| 4763 | // bad_node = *op1; | 4765 | op2_array_val = op2_val; |
| 4764 | // } else if (!op2_val->ok) { | 4766 | op2_array_index = 0; |
| 4765 | // bad_node = *op2; | 4767 | op2_array_end = op2_array_val->data.x_array.size; |
| 4766 | // } else { | 4768 | } else if (op2_canon_type->id == TypeTableEntryIdPointer && |
| 4767 | // bad_node = nullptr; | 4769 | op2_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 && |
| 4768 | // } | 4770 | op2_val->data.x_ptr.special == ConstPtrSpecialCStr) |
| 4769 | // if (bad_node) { | 4771 | { |
| 4770 | // add_node_error(g, bad_node, buf_sprintf("array concatenation requires constant expression")); | 4772 | if (child_type != ira->codegen->builtin_types.entry_u8) { |
| 4771 | // return g->builtin_types.entry_invalid; | 4773 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", |
| 4772 | // } | 4774 | buf_ptr(&child_type->name), |
| 4773 | // | 4775 | buf_ptr(&op2->type_entry->name))); |
| 4774 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | 4776 | return ira->codegen->builtin_types.entry_invalid; |
| 4775 | // const_val->ok = true; | 4777 | } |
| 4776 | // const_val->depends_on_compile_var = op1_val->depends_on_compile_var || | 4778 | op2_array_val = op2_val->data.x_ptr.base_ptr; |
| 4777 | // op2_val->depends_on_compile_var; | 4779 | op2_array_index = op2_val->data.x_ptr.index; |
| 4778 | // | 4780 | op2_array_end = op2_array_val->data.x_array.size - 1; |
| 4779 | // if (op1_type->id == TypeTableEntryIdArray) { | 4781 | } else { |
| 4780 | // uint64_t new_len = op1_type->data.array.len + op2_type->data.array.len; | 4782 | ir_add_error(ira, op2, |
| 4781 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(new_len); | 4783 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->type_entry->name))); |
| 4782 | // uint64_t next_index = 0; | 4784 | // TODO if meta_type is type decl, add note pointing to type decl declaration |
| 4783 | // for (uint64_t i = 0; i < op1_type->data.array.len; i += 1, next_index += 1) { | 4785 | return ira->codegen->builtin_types.entry_invalid; |
| 4784 | // const_val->data.x_array.fields[next_index] = op1_val->data.x_array.fields[i]; | 4786 | } |
| 4785 | // } | 4787 | |
| 4786 | // for (uint64_t i = 0; i < op2_type->data.array.len; i += 1, next_index += 1) { | 4788 | bool depends_on_compile_var = op1->static_value.depends_on_compile_var || op2->static_value.depends_on_compile_var; |
| 4787 | // const_val->data.x_array.fields[next_index] = op2_val->data.x_array.fields[i]; | 4789 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| 4788 | // } | 4790 | |
| 4789 | // return get_array_type(g, child_type, new_len); | 4791 | TypeTableEntry *result_type; |
| 4790 | // } else if (op1_type->id == TypeTableEntryIdPointer) { | 4792 | ConstExprValue *out_array_val; |
| 4791 | // if (!op1_val->data.x_ptr.is_c_str) { | 4793 | size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index); |
| 4792 | // add_node_error(g, *op1, | 4794 | if (op1_canon_type->id == TypeTableEntryIdArray || op2_canon_type->id == TypeTableEntryIdArray) { |
| 4793 | // buf_sprintf("expected array or C string literal, found '%s'", | 4795 | result_type = get_array_type(ira->codegen, child_type, new_len); |
| 4794 | // buf_ptr(&op1_type->name))); | 4796 | |
| 4795 | // return g->builtin_types.entry_invalid; | 4797 | out_array_val = out_val; |
| 4796 | // } else if (!op2_val->data.x_ptr.is_c_str) { | 4798 | } else { |
| 4797 | // add_node_error(g, *op2, | 4799 | result_type = get_pointer_to_type(ira->codegen, child_type, true); |
| 4798 | // buf_sprintf("expected array or C string literal, found '%s'", | 4800 | |
| 4799 | // buf_ptr(&op2_type->name))); | 4801 | out_array_val = allocate<ConstExprValue>(1); |
| 4800 | // return g->builtin_types.entry_invalid; | 4802 | out_array_val->special = ConstValSpecialStatic; |
| 4801 | // } | 4803 | out_val->data.x_ptr.base_ptr = out_array_val; |
| 4802 | // const_val->data.x_ptr.is_c_str = true; | 4804 | out_val->data.x_ptr.index = 0; |
| 4803 | // const_val->data.x_ptr.len = op1_val->data.x_ptr.len + op2_val->data.x_ptr.len - 1; | 4805 | out_val->data.x_ptr.special = ConstPtrSpecialCStr; |
| 4804 | // const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(const_val->data.x_ptr.len); | 4806 | |
| 4805 | // uint64_t next_index = 0; | 4807 | new_len += 1; // null byte |
| 4806 | // for (uint64_t i = 0; i < op1_val->data.x_ptr.len - 1; i += 1, next_index += 1) { | 4808 | } |
| 4807 | // const_val->data.x_ptr.ptr[next_index] = op1_val->data.x_ptr.ptr[i]; | 4809 | out_array_val->data.x_array.elements = allocate<ConstExprValue>(new_len); |
| 4808 | // } | 4810 | out_array_val->data.x_array.size = new_len; |
| 4809 | // for (uint64_t i = 0; i < op2_val->data.x_ptr.len; i += 1, next_index += 1) { | 4811 | |
| 4810 | // const_val->data.x_ptr.ptr[next_index] = op2_val->data.x_ptr.ptr[i]; | 4812 | size_t next_index = 0; |
| 4811 | // } | 4813 | for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) { |
| 4812 | // return op1_type; | 4814 | out_array_val->data.x_array.elements[next_index] = op1_array_val->data.x_array.elements[i]; |
| 4813 | // } else { | 4815 | } |
| 4814 | // zig_unreachable(); | 4816 | for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) { |
| 4815 | // } | 4817 | out_array_val->data.x_array.elements[next_index] = op2_array_val->data.x_array.elements[i]; |
| 4816 | zig_panic("TODO"); | 4818 | } |
| | 4819 | if (next_index < new_len) { |
| | 4820 | ConstExprValue *null_byte = &out_array_val->data.x_array.elements[next_index]; |
| | 4821 | null_byte->special = ConstValSpecialStatic; |
| | 4822 | bignum_init_unsigned(&null_byte->data.x_bignum, 0); |
| | 4823 | next_index += 1; |
| | 4824 | } |
| | 4825 | assert(next_index == new_len); |
| | 4826 | |
| | 4827 | return result_type; |
| 4817 | } | 4828 | } |
| 4818 | | 4829 | |
| 4819 | static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 4830 | static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) { |