authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-11 18:43:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-11 18:43:52-05:00
loga963fba246819e8b71777db157ad9578086ea16e
tree8030c925ed4e5cc6528191a8dd903340a5d1d8da
parentdf0cdceff7c84510662b9fa3e698ff36c31b1ede

IR: implement compile time array concatenation


1 files changed, 109 insertions(+), 98 deletions(-)

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