diff options
| author | Veikka Tuominen <git@vexu.eu> | 2020-09-14 16:43:49 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-14 16:43:49 +0300 |
| commit | d073836894df8b9fb56f24f577a51dd09a85a932 (patch) | |
| tree | 920723ea7cbe577934f0fb9670332f40dc7fd94a /src/ir.cpp | |
| parent | c49435f76b07cbf3fdd6a10303a1a0ee4290e59a (diff) | |
| parent | acdf1f0bde9a07cae2fbe33739f5f4aee7989f7b (diff) | |
| download | zig-d073836894df8b9fb56f24f577a51dd09a85a932.tar.gz zig-d073836894df8b9fb56f24f577a51dd09a85a932.zip | |
Merge pull request #6172 from tadeokondrak/@Type(.Union)
Implement @Type for Union
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 105 |
1 files changed, 85 insertions, 20 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 803b97891f..6cb5d8bc2d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25424,8 +25424,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false); - ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr); - for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) { TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index]; ZigValue *union_field_val = &union_field_array->data.x_array.data.s_none.elements[union_field_index]; @@ -25433,20 +25431,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy union_field_val->special = ConstValSpecialStatic; union_field_val->type = type_info_union_field_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2); inner_fields[1]->special = ConstValSpecialStatic; - inner_fields[1]->type = get_optional_type(ira->codegen, type_info_enum_field_type); - - if (fields[1]->data.x_optional == nullptr) { - inner_fields[1]->data.x_optional = nullptr; - } else { - inner_fields[1]->data.x_optional = ira->codegen->pass1_arena->create<ZigValue>(); - make_enum_field_val(ira, inner_fields[1]->data.x_optional, union_field->enum_field, type_info_enum_field_type); - } - - inner_fields[2]->special = ConstValSpecialStatic; - inner_fields[2]->type = ira->codegen->builtin_types.entry_type; - inner_fields[2]->data.x_type = union_field->type_entry; + inner_fields[1]->type = ira->codegen->builtin_types.entry_type; + inner_fields[1]->data.x_type = union_field->type_entry; ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee; init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true); @@ -26102,7 +26090,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI entry->data.structure.layout = layout; entry->data.structure.special = is_tuple ? StructSpecialInferredTuple : StructSpecialNone; entry->data.structure.created_by_at_type = true; - entry->data.structure.decls_scope = create_decls_scope(ira->codegen, nullptr, nullptr, entry, entry, &entry->name); + entry->data.structure.decls_scope = create_decls_scope( + ira->codegen, source_instr->source_node, source_instr->scope, entry, get_scope_import(source_instr->scope), &entry->name); assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0); @@ -26226,13 +26215,89 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI return ira->codegen->invalid_inst_gen->value->type; field->value = *field_int_value; } + return entry; + } + case ZigTypeIdUnion: { + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr)); + ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0); + if (layout_value == nullptr) + return ira->codegen->invalid_inst_gen->value->type; + assert(layout_value->special == ConstValSpecialStatic); + assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr)); + ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag); + + ZigType *tag_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "tag_type", 1); + if (tag_type != nullptr && type_is_invalid(tag_type)) { + return ira->codegen->invalid_inst_gen->value->type; + } + if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) { + ir_add_error(ira, source_instr, buf_sprintf( + "expected enum type, found '%s'", type_id_name(tag_type->id))); + return ira->codegen->invalid_inst_gen->value->type; + } + + ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2); + if (fields_value == nullptr) + return ira->codegen->invalid_inst_gen->value->type; + + assert(fields_value->special == ConstValSpecialStatic); + assert(is_slice(fields_value->type)); + ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index]; + ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index]; + size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint); + + ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 3); + if (decls_value == nullptr) + return ira->codegen->invalid_inst_gen->value->type; + + assert(decls_value->special == ConstValSpecialStatic); + assert(is_slice(decls_value->type)); + ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index]; + size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint); + if (decls_len != 0) { + ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Union.decls must be empty for @Type")); + return ira->codegen->invalid_inst_gen->value->type; + } + + ZigType *entry = new_type_table_entry(ZigTypeIdUnion); + buf_init_from_buf(&entry->name, + get_anon_type_name(ira->codegen, ira->old_irb.exec, "union", source_instr->scope, source_instr->source_node, &entry->name)); + entry->data.unionation.decl_node = source_instr->source_node; + entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len); + entry->data.unionation.fields_by_name.init(fields_len); + entry->data.unionation.decls_scope = create_decls_scope( + ira->codegen, source_instr->source_node, source_instr->scope, entry, get_scope_import(source_instr->scope), &entry->name); + entry->data.unionation.tag_type = tag_type; + entry->data.unionation.src_field_count = fields_len; + entry->data.unionation.layout = layout; + + assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); + assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0); + ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val; + assert(fields_arr->special == ConstValSpecialStatic); + assert(fields_arr->data.x_array.special == ConstArraySpecialNone); + for (size_t i = 0; i < fields_len; i++) { + ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i]; + assert(field_value->type == ir_type_info_get_type(ira, "UnionField", nullptr)); + TypeUnionField *field = &entry->data.unionation.fields[i]; + field->name = buf_alloc(); + if ((err = get_const_field_buf(ira, source_instr->source_node, field_value, "name", 0, field->name))) + return ira->codegen->invalid_inst_gen->value->type; + if (entry->data.unionation.fields_by_name.put_unique(field->name, field) != nullptr) { + ir_add_error(ira, source_instr, buf_sprintf("duplicate union field '%s'", buf_ptr(field->name))); + return ira->codegen->invalid_inst_gen->value->type; + } + field->decl_node = source_instr->source_node; + ZigValue *type_value = get_const_field(ira, source_instr->source_node, field_value, "field_type", 1); + if (type_value == nullptr) + return ira->codegen->invalid_inst_gen->value->type; + field->type_val = type_value; + field->type_entry = type_value->data.x_type; + } return entry; } - case ZigTypeIdUnion: - ir_add_error(ira, source_instr, buf_sprintf( - "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); - return ira->codegen->invalid_inst_gen->value->type; case ZigTypeIdFn: case ZigTypeIdBoundFn: ir_add_error(ira, source_instr, buf_sprintf( |
