IR: implement compile time array concatenation

This commit is contained in:
Andrew Kelley 2016-12-11 18:43:52 -05:00
parent df0cdceff7
commit a963fba246

View File

@ -4711,109 +4711,120 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {
IrInstruction *op1 = instruction->op1->other; IrInstruction *op1 = instruction->op1->other;
if (op1->type_entry->id == TypeTableEntryIdInvalid) TypeTableEntry *op1_canon_type = get_underlying_type(op1->type_entry);
if (op1_canon_type->id == TypeTableEntryIdInvalid)
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
IrInstruction *op2 = instruction->op2->other; IrInstruction *op2 = instruction->op2->other;
if (op2->type_entry->id == TypeTableEntryIdInvalid) TypeTableEntry *op2_canon_type = get_underlying_type(op2->type_entry);
if (op2_canon_type->id == TypeTableEntryIdInvalid)
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
// AstNode **op1 = node->data.bin_op_expr.op1->parent_field; ConstExprValue *op1_val = ir_resolve_const(ira, op1);
// AstNode **op2 = node->data.bin_op_expr.op2->parent_field; if (!op1_val)
// return ira->codegen->builtin_types.entry_invalid;
// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
// TypeTableEntry *child_type; ConstExprValue *op2_val = ir_resolve_const(ira, op2);
// if (op1_type->id == TypeTableEntryIdInvalid) { if (!op2_val)
// return g->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
// } else if (op1_type->id == TypeTableEntryIdArray) {
// child_type = op1_type->data.array.child_type; ConstExprValue *op1_array_val;
// } else if (op1_type->id == TypeTableEntryIdPointer && size_t op1_array_index;
// op1_type->data.pointer.child_type == g->builtin_types.entry_u8) { size_t op1_array_end;
// child_type = op1_type->data.pointer.child_type; TypeTableEntry *child_type;
// } else { if (op1_canon_type->id == TypeTableEntryIdArray) {
// add_node_error(g, *op1, buf_sprintf("expected array or C string literal, found '%s'", child_type = op1_canon_type->data.array.child_type;
// buf_ptr(&op1_type->name))); op1_array_val = op1_val;
// return g->builtin_types.entry_invalid; op1_array_index = 0;
// } op1_array_end = op1_val->data.x_array.size;
// } else if (op1_canon_type->id == TypeTableEntryIdPointer &&
// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); op1_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
// op1_val->data.x_ptr.special == ConstPtrSpecialCStr)
// if (op2_type->id == TypeTableEntryIdInvalid) { {
// return g->builtin_types.entry_invalid; child_type = op1_canon_type->data.pointer.child_type;
// } else if (op2_type->id == TypeTableEntryIdArray) { op1_array_val = op1_val->data.x_ptr.base_ptr;
// if (op2_type->data.array.child_type != child_type) { op1_array_index = op1_val->data.x_ptr.index;
// add_node_error(g, *op2, buf_sprintf("expected array of type '%s', found '%s'", op1_array_end = op1_array_val->data.x_array.size - 1;
// buf_ptr(&child_type->name), } else {
// buf_ptr(&op2_type->name))); ir_add_error(ira, op1,
// return g->builtin_types.entry_invalid; buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->type_entry->name)));
// } // TODO if meta_type is type decl, add note pointing to type decl declaration
// } else if (op2_type->id == TypeTableEntryIdPointer && return ira->codegen->builtin_types.entry_invalid;
// op2_type->data.pointer.child_type == g->builtin_types.entry_u8) { }
// } else {
// add_node_error(g, *op2, buf_sprintf("expected array or C string literal, found '%s'", ConstExprValue *op2_array_val;
// buf_ptr(&op2_type->name))); size_t op2_array_index;
// return g->builtin_types.entry_invalid; size_t op2_array_end;
// } if (op2_canon_type->id == TypeTableEntryIdArray) {
// if (op2_canon_type->data.array.child_type != child_type) {
// ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
// ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; buf_ptr(&child_type->name),
// buf_ptr(&op2->type_entry->name)));
// AstNode *bad_node; return ira->codegen->builtin_types.entry_invalid;
// if (!op1_val->ok) { }
// bad_node = *op1; op2_array_val = op2_val;
// } else if (!op2_val->ok) { op2_array_index = 0;
// bad_node = *op2; op2_array_end = op2_array_val->data.x_array.size;
// } else { } else if (op2_canon_type->id == TypeTableEntryIdPointer &&
// bad_node = nullptr; op2_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
// } op2_val->data.x_ptr.special == ConstPtrSpecialCStr)
// if (bad_node) { {
// add_node_error(g, bad_node, buf_sprintf("array concatenation requires constant expression")); if (child_type != ira->codegen->builtin_types.entry_u8) {
// return g->builtin_types.entry_invalid; ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
// } buf_ptr(&child_type->name),
// buf_ptr(&op2->type_entry->name)));
// ConstExprValue *const_val = &get_resolved_expr(node)->const_val; return ira->codegen->builtin_types.entry_invalid;
// const_val->ok = true; }
// const_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_array_val = op2_val->data.x_ptr.base_ptr;
// op2_val->depends_on_compile_var; op2_array_index = op2_val->data.x_ptr.index;
// op2_array_end = op2_array_val->data.x_array.size - 1;
// if (op1_type->id == TypeTableEntryIdArray) { } else {
// uint64_t new_len = op1_type->data.array.len + op2_type->data.array.len; ir_add_error(ira, op2,
// const_val->data.x_array.fields = allocate<ConstExprValue*>(new_len); buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->type_entry->name)));
// uint64_t next_index = 0; // TODO if meta_type is type decl, add note pointing to type decl declaration
// for (uint64_t i = 0; i < op1_type->data.array.len; i += 1, next_index += 1) { return ira->codegen->builtin_types.entry_invalid;
// const_val->data.x_array.fields[next_index] = op1_val->data.x_array.fields[i]; }
// }
// for (uint64_t i = 0; i < op2_type->data.array.len; i += 1, next_index += 1) { bool depends_on_compile_var = op1->static_value.depends_on_compile_var || op2->static_value.depends_on_compile_var;
// const_val->data.x_array.fields[next_index] = op2_val->data.x_array.fields[i]; ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
// }
// return get_array_type(g, child_type, new_len); TypeTableEntry *result_type;
// } else if (op1_type->id == TypeTableEntryIdPointer) { ConstExprValue *out_array_val;
// if (!op1_val->data.x_ptr.is_c_str) { size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
// add_node_error(g, *op1, if (op1_canon_type->id == TypeTableEntryIdArray || op2_canon_type->id == TypeTableEntryIdArray) {
// buf_sprintf("expected array or C string literal, found '%s'", result_type = get_array_type(ira->codegen, child_type, new_len);
// buf_ptr(&op1_type->name)));
// return g->builtin_types.entry_invalid; out_array_val = out_val;
// } else if (!op2_val->data.x_ptr.is_c_str) { } else {
// add_node_error(g, *op2, result_type = get_pointer_to_type(ira->codegen, child_type, true);
// buf_sprintf("expected array or C string literal, found '%s'",
// buf_ptr(&op2_type->name))); out_array_val = allocate<ConstExprValue>(1);
// return g->builtin_types.entry_invalid; out_array_val->special = ConstValSpecialStatic;
// } out_val->data.x_ptr.base_ptr = out_array_val;
// const_val->data.x_ptr.is_c_str = true; out_val->data.x_ptr.index = 0;
// const_val->data.x_ptr.len = op1_val->data.x_ptr.len + op2_val->data.x_ptr.len - 1; out_val->data.x_ptr.special = ConstPtrSpecialCStr;
// const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(const_val->data.x_ptr.len);
// uint64_t next_index = 0; new_len += 1; // null byte
// for (uint64_t i = 0; i < op1_val->data.x_ptr.len - 1; i += 1, next_index += 1) { }
// const_val->data.x_ptr.ptr[next_index] = op1_val->data.x_ptr.ptr[i]; out_array_val->data.x_array.elements = allocate<ConstExprValue>(new_len);
// } out_array_val->data.x_array.size = new_len;
// for (uint64_t i = 0; i < op2_val->data.x_ptr.len; i += 1, next_index += 1) {
// const_val->data.x_ptr.ptr[next_index] = op2_val->data.x_ptr.ptr[i]; size_t next_index = 0;
// } for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
// return op1_type; out_array_val->data.x_array.elements[next_index] = op1_array_val->data.x_array.elements[i];
// } else { }
// zig_unreachable(); for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
// } out_array_val->data.x_array.elements[next_index] = op2_array_val->data.x_array.elements[i];
zig_panic("TODO"); }
if (next_index < new_len) {
ConstExprValue *null_byte = &out_array_val->data.x_array.elements[next_index];
null_byte->special = ConstValSpecialStatic;
bignum_init_unsigned(&null_byte->data.x_bignum, 0);
next_index += 1;
}
assert(next_index == new_len);
return result_type;
} }
static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) { static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) {