aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-07-19 12:15:21 +0100
committerGinger Bill <bill@gingerbill.org>2017-07-19 12:15:21 +0100
commit6113164211d5bd010ea324594d69668e5732817d (patch)
treee31315edbdaefdc698dae9d5f78b1555207d97f4 /src/ir.cpp
parent4db462a703d506f2ef23a16921a23a10115feacb (diff)
Change union layout to store type info rather than an integer; ternary expression for types with constant condition
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp82
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));
}