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...@@ -4711,109 +4711,120 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
47114711
4712static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {4712static 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;
47164717
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;
47204722
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}
48184829
4819static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) {4830static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) {