diff options
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 124 |
1 files changed, 27 insertions, 97 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 455dae9d2..43c1cca31 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -966,7 +966,9 @@ 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 = make_type_pointer(p->module->allocator, t_type_info_ptr); + // i->UnionTagPtr.type = make_type_pointer(p->module->allocator, t_type_info_ptr); + Type *u = type_deref(ir_type(address)); + i->UnionTagPtr.type = make_type_pointer(p->module->allocator, union_tag_type(u)); return v; } @@ -974,7 +976,10 @@ 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_type_info_ptr; + // i->UnionTagValue.type = t_type_info_ptr; + // i->UnionTagValue.type = t_int; + Type *u = type_deref(ir_type(address)); + i->UnionTagPtr.type = union_tag_type(u); return v; } @@ -2236,10 +2241,6 @@ irValue *ir_emit_union_tag_ptr(irProcedure *proc, irValue *u) { GB_ASSERT_MSG(is_type_pointer(t) && is_type_union(type_deref(t)), "%s", type_to_string(t)); irValue *tag_ptr = ir_emit(proc, ir_instr_union_tag_ptr(proc, u)); - Type *tpt = ir_type(tag_ptr); - GB_ASSERT(is_type_pointer(tpt)); - tpt = base_type(type_deref(tpt)); - GB_ASSERT(tpt == t_type_info_ptr); return tag_ptr; } @@ -2784,6 +2785,10 @@ irValue *ir_find_or_add_entity_string(irModule *m, String str) { } +irValue *ir_const_union_tag(gbAllocator a, Type *u, Type *v) { + return ir_value_constant(a, union_tag_type(u), exact_value_i64(union_variant_index(u, v))); +} + String ir_lookup_subtype_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { Type *prev_src = src; @@ -3011,7 +3016,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_type_info(proc, vt)); + ir_emit_store(proc, tag_ptr, ir_const_union_tag(a, t, src_type)); return ir_emit_load(proc, parent); } @@ -3233,6 +3238,7 @@ irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t) { } + irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, TokenPos pos) { gbAllocator a = proc->module->allocator; @@ -3248,77 +3254,6 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token irValue *v = ir_add_local_generated(proc, tuple); - #if 0 - if (is_ptr) { - Type *src = base_type(type_deref(src_type)); - Type *src_ptr = src_type; - GB_ASSERT(is_type_union(src)); - Type *dst_ptr = tuple->Tuple.variables[0]->type; - Type *dst = type_deref(dst_ptr); - - irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value)); - irValue *dst_tag = nullptr; - for (isize i = 1; i < src->Struct.variant_count; i++) { - Type *vt = src->Struct.variants[i]; - if (are_types_identical(vt, dst)) { - dst_tag = ir_const_int(a, i); - break; - } - } - GB_ASSERT(dst_tag != nullptr); - - irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok"); - irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end"); - irValue *cond = ir_emit_comp(proc, Token_CmpEq, tag, dst_tag); - ir_emit_if(proc, cond, ok_block, end_block); - ir_start_block(proc, ok_block); - - irValue *gep0 = ir_emit_struct_ep(proc, v, 0); - irValue *gep1 = ir_emit_struct_ep(proc, v, 1); - - irValue *data = ir_emit_conv(proc, value, dst_ptr); - ir_emit_store(proc, gep0, data); - ir_emit_store(proc, gep1, v_true); - - ir_emit_jump(proc, end_block); - ir_start_block(proc, end_block); - - } else { - Type *src = base_type(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->Struct.variant_count; i++) { - Type *vt = src->Struct.variants[i]; - if (are_types_identical(vt, dst)) { - dst_tag = ir_const_int(a, i); - break; - } - } - GB_ASSERT(dst_tag != nullptr); - - irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok"); - irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end"); - irValue *cond = ir_emit_comp(proc, Token_CmpEq, tag, dst_tag); - ir_emit_if(proc, cond, ok_block, end_block); - ir_start_block(proc, ok_block); - - irValue *gep0 = ir_emit_struct_ep(proc, v, 0); - irValue *gep1 = ir_emit_struct_ep(proc, v, 1); - - irValue *data = ir_emit_load(proc, ir_emit_conv(proc, value_, ir_type(gep0))); - ir_emit_store(proc, gep0, data); - ir_emit_store(proc, gep1, v_true); - - ir_emit_jump(proc, end_block); - ir_start_block(proc, end_block); - } - #else if (is_ptr) { value = ir_emit_load(proc, value); } @@ -3326,10 +3261,11 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token GB_ASSERT(is_type_union(src)); Type *dst = tuple->Tuple.variables[0]->type; - 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 = ir_type_info(proc, 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 = ir_const_union_tag(a, src, dst); + irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok"); irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end"); @@ -3346,7 +3282,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token ir_emit_jump(proc, end_block); ir_start_block(proc, end_block); - #endif + if (!is_tuple) { // NOTE(bill): Panic on invalid conversion Type *dst_type = tuple->Tuple.variables[0]->type; @@ -7073,18 +7009,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { case_type = type_of_expr(proc->module->info, cc->list[type_index]); irValue *cond = nullptr; if (match_type_kind == MatchType_Union) { - Type *bt = type_deref(case_type); - irValue *variant_tag = nullptr; Type *ut = base_type(type_deref(parent_type)); - GB_ASSERT(ut->kind == Type_Union); - for_array(variant_index, ut->Union.variants) { - Type *vt = ut->Union.variants[variant_index]; - if (are_types_identical(vt, bt)) { - variant_tag = ir_type_info(proc, vt); - break; - } - } - GB_ASSERT(variant_tag != nullptr); + irValue *variant_tag = ir_const_union_tag(proc->module->allocator, ut, case_type); 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)); @@ -8414,6 +8340,7 @@ void ir_gen_tree(irGen *s) { { irValue *variant_types = ir_emit_struct_ep(proc, tag, 0); irValue *tag_offset_ptr = ir_emit_struct_ep(proc, tag, 1); + irValue *tag_type_ptr = ir_emit_struct_ep(proc, tag, 2); isize variant_count = gb_max(0, t->Union.variants.count); irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count); @@ -8431,8 +8358,10 @@ 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); + i64 tag_size = union_tag_size(t); + i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size); ir_emit_store(proc, tag_offset_ptr, ir_const_int(a, tag_offset)); + ir_emit_store(proc, tag_type_ptr, ir_type_info(proc, union_tag_type(t))); } break; @@ -8556,11 +8485,12 @@ void ir_gen_tree(irGen *s) { if (tag != nullptr) { Type *tag_type = type_deref(ir_type(tag)); GB_ASSERT(is_type_named(tag_type)); - irValue *ti = ir_type_info(proc, tag_type); + Type *variant_type = type_deref(ir_type(variant_ptr)); + irValue *tag = ir_const_union_tag(a, variant_type, tag_type); irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr); - ir_emit_store(proc, ptr, ti); + ir_emit_store(proc, ptr, tag); } else { - GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t)); + GB_PANIC("Unhandled Type_Info variant: %s", type_to_string(t)); } } } |