aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-10-08 15:16:13 +0100
committerGinger Bill <bill@gingerbill.org>2017-10-08 15:16:13 +0100
commit6424966b7ad6f85dc56d72cf623276f788a1a157 (patch)
tree063d3063c885f331b71c51844f35a85d19af1f75 /src/ir.cpp
parent4e42d7df4303470dec5b3c354a9469699f6abf8d (diff)
Union tag stored as an integer
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp124
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));
}
}
}