diff options
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 82 |
1 files changed, 26 insertions, 56 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 85eef66c4..833edb0e2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -954,7 +954,7 @@ irValue *ir_instr_union_tag_ptr(irProcedure *p, irValue *address) { irValue *v = ir_alloc_instr(p, irInstr_UnionTagPtr); irInstr *i = &v->Instr; i->UnionTagPtr.address = address; - i->UnionTagPtr.type = t_int_ptr; + i->UnionTagPtr.type = make_type_pointer(p->module->allocator, t_type_info_ptr); return v; } @@ -962,7 +962,7 @@ irValue *ir_instr_union_tag_value(irProcedure *p, irValue *address) { irValue *v = ir_alloc_instr(p, irInstr_UnionTagValue); irInstr *i = &v->Instr; i->UnionTagValue.address = address; - i->UnionTagValue.type = t_int; + i->UnionTagValue.type = t_type_info_ptr; return v; } @@ -2218,7 +2218,7 @@ irValue *ir_emit_union_tag_ptr(irProcedure *proc, irValue *u) { Type *tpt = ir_type(tag_ptr); GB_ASSERT(is_type_pointer(tpt)); tpt = base_type(type_deref(tpt)); - GB_ASSERT(tpt == t_int); + GB_ASSERT(tpt == t_type_info_ptr); return tag_ptr; } @@ -2379,15 +2379,8 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT_MSG(gb_is_between(index, 0, t->Record.field_count-1), "0..%d..%d", index, t->Record.field_count); result_type = make_type_pointer(a, t->Record.fields[index]->type); } else if (is_type_union(t)) { - type_set_offsets(a, t); - GB_ASSERT(t->Record.field_count > 0); - if (index == -1) { - index = t->Record.field_count+1; - result_type = t_int_ptr; - } else { - GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); - result_type = make_type_pointer(a, t->Record.fields[index]->type); - } + GB_ASSERT(index == -1); + return ir_emit_union_tag_ptr(proc, s); } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variable_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); @@ -2449,14 +2442,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); result_type = t->Record.fields[index]->type; } else if (is_type_union(t)) { - type_set_offsets(a, t); - if (index == -1) { - index = t->Record.field_count+1; - result_type = t_int_ptr; - } else { - GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); - } - result_type = t->Record.fields[index]->type; + GB_ASSERT(index == -1); + return ir_emit_union_tag_value(proc, s); } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variable_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); @@ -2523,12 +2510,12 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) { if (is_type_raw_union(type)) { type = type->Record.fields[index]->type; e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type)); + } else if (type->kind == Type_Union) { + GB_ASSERT(index == -1); + type = t_type_info_ptr; + e = ir_emit_struct_ep(proc, e, index); } else if (type->kind == Type_Record) { - if (index == -1) { - type = t_int; - } else { - type = type->Record.fields[index]->type; - } + type = type->Record.fields[index]->type; e = ir_emit_struct_ep(proc, e, index); } else if (type->kind == Type_Tuple) { type = type->Tuple.variables[index]->type; @@ -2983,7 +2970,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { ir_emit_store(proc, underlying, value); irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent); - ir_emit_store(proc, tag_ptr, ir_const_int(a, i)); + ir_emit_store(proc, tag_ptr, ir_type_info(proc, vt)); return ir_emit_load(proc, parent); } @@ -3308,20 +3295,11 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token Type *src = base_type(type_deref(src_type)); GB_ASSERT(is_type_union(src)); Type *dst = tuple->Tuple.variables[0]->type; - Type *dst_ptr = make_type_pointer(a, dst); irValue *value_ = ir_address_from_load_or_generate_local(proc, value); irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_)); - irValue *dst_tag = nullptr; - for (isize i = 1; i < src->Union.variant_count; i++) { - Type *vt = src->Union.variants[i]; - if (are_types_identical(vt, dst)) { - dst_tag = ir_const_int(a, i); - break; - } - } - GB_ASSERT(dst_tag != nullptr); + irValue *dst_tag = ir_type_info(proc, dst); irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok"); irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end"); @@ -6943,18 +6921,18 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *cond = nullptr; if (match_type_kind == MatchType_Union) { Type *bt = type_deref(case_type); - irValue *index = nullptr; + irValue *variant_tag = nullptr; Type *ut = base_type(type_deref(parent_type)); GB_ASSERT(ut->kind == Type_Union); for (isize variant_index = 1; variant_index < ut->Union.variant_count; variant_index++) { Type *vt = ut->Union.variants[variant_index]; if (are_types_identical(vt, bt)) { - index = ir_const_int(allocator, variant_index); + variant_tag = ir_type_info(proc, vt); break; } } - GB_ASSERT(index != nullptr); - cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index); + GB_ASSERT(variant_tag != nullptr); + cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag); } else if (match_type_kind == MatchType_Any) { irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); irValue *case_ti = ir_type_info(proc, case_type); @@ -8166,7 +8144,8 @@ void ir_gen_tree(irGen *s) { tag = ir_emit_conv(proc, variant_ptr, t_type_info_union_ptr); { - irValue *variant_types = ir_emit_struct_ep(proc, tag, 0); + irValue *variant_types = ir_emit_struct_ep(proc, tag, 0); + irValue *tag_offset_ptr = ir_emit_struct_ep(proc, tag, 1); isize variant_count = gb_max(0, t->Union.variant_count-1); irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count); @@ -8183,6 +8162,9 @@ void ir_gen_tree(irGen *s) { irValue *count = ir_const_int(a, variant_count); ir_fill_slice(proc, variant_types, memory_types, count, count); + + i64 tag_offset = align_formula(t->Union.variant_block_size, build_context.word_size); + ir_emit_store(proc, tag_offset_ptr, ir_const_int(a, tag_offset)); } } break; @@ -8323,21 +8305,9 @@ void ir_gen_tree(irGen *s) { if (tag != nullptr) { Type *tag_type = type_deref(ir_type(tag)); GB_ASSERT(is_type_named(tag_type)); - Type *ti = base_type(t_type_info); - Type *tiv = base_type(ti->Record.fields_in_src_order[2]->type); - GB_ASSERT(is_type_union(tiv)); - bool found = false; - for (isize i = 1; i < tiv->Union.variant_count; i++) { - Type *vt = tiv->Union.variants[i]; - if (are_types_identical(vt, tag_type)) { - found = true; - irValue *tag_val = ir_const_int(a, i); - irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr); - ir_emit_store(proc, ptr, tag_val); - break; - } - } - GB_ASSERT_MSG(found, "Tag type not found: %s", type_to_string(tag_type)); + irValue *ti = ir_type_info(proc, tag_type); + irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr); + ir_emit_store(proc, ptr, ti); } else { GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t)); } |