diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-03 18:18:45 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-03 18:18:45 +0100 |
| commit | 7f884ed25187416bb3994e498eae30fe65233940 (patch) | |
| tree | d7386614920f6d56ea184efd638d9132a34ea682 /src/codegen | |
| parent | 11205f968ad2bf4893fa75df3fc3331f960039d1 (diff) | |
Start implementing Tagged Unions
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/print_llvm.cpp | 10 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 29 |
2 files changed, 36 insertions, 3 deletions
diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 6f63c0108..ecbf48d54 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -158,6 +158,10 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) { ssa_fprintf(f, ">"); } break; + case TypeRecord_Union: { + i64 size_of_union = type_size_of(s, gb_heap_allocator(), t) - s.word_size; + ssa_fprintf(f, "{i%lld, [%lld x i8]}", word_bits, size_of_union); + } break; case TypeRecord_RawUnion: ssa_fprintf(f, "[%lld x i8]", type_size_of(s, gb_heap_allocator(), t)); break; @@ -172,7 +176,7 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) { ssa_fprintf(f, "*"); break; case Type_Named: - if (is_type_struct(t)) { + if (is_type_struct(t) || is_type_union(t)) { ssa_print_encoded_local(f, t->Named.name); } else { ssa_print_type(f, s, get_base_type(t)); @@ -454,7 +458,6 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "%%%d = ", value->id); if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) { - if (is_type_string(elem_type)) { ssa_fprintf(f, "call "); ssa_print_type(f, m->sizes, t_bool); @@ -756,8 +759,9 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) { void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) { GB_ASSERT(v->kind == ssaValue_TypeName); Type *base_type = get_base_type(ssa_type(v)); - if (!is_type_struct(base_type)) + if (!is_type_struct(base_type) && !is_type_union(base_type)) { return; + } ssa_print_encoded_local(f, v->TypeName.name); ssa_fprintf(f, " = type "); ssa_print_type(f, m->sizes, get_base_type(v->TypeName.type)); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 24a350034..251a76de6 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -1432,6 +1432,34 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_inttoptr, value, src, dst)); } + if (is_type_union(dst)) { + for (isize i = 0; i < dst->Record.field_count; i++) { + Entity *f = dst->Record.fields[i]; + if (are_types_identical(f->type, src_type)) { + gbAllocator allocator = proc->module->allocator; + ssaValue *parent = ssa_add_local_generated(proc, t); + ssaValue *tag = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(i)); + ssa_emit_store(proc, ssa_emit_struct_gep(proc, parent, v_zero32, t_int), tag); + + i64 int_size = proc->module->sizes.word_size; + i64 underlying_array_size = type_size_of(proc->module->sizes, allocator, ssa_type(parent)); + underlying_array_size -= int_size; + Type *array_type = make_type_array(allocator, t_u8, underlying_array_size); + ssaValue *data = ssa_emit_struct_gep(proc, parent, v_one32, array_type); + data = ssa_array_elem(proc, data); + + Type *tag_type = src_type; + Type *t_u8_ptr = make_type_pointer(allocator, t_u8); + Type *tag_type_ptr = make_type_pointer(allocator, tag_type); + ssaValue *underlying = ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, data, t_u8_ptr, tag_type_ptr)); + // underlying = ssa_emit_zero_gep(proc, underlying); + // ssa_set_type(underlying, src); + // ssa_emit_store(proc, underlying, value); + + return ssa_emit_load(proc, parent); + } + } + } // NOTE(bill): This has to be done beofre `Pointer <-> Pointer` as it's // subtype polymorphism casting @@ -1660,6 +1688,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case Token_GtEq: { ssaValue *left = ssa_build_expr(proc, be->left); ssaValue *right = ssa_build_expr(proc, be->right); + ssaValue *cmp = ssa_emit_comp(proc, be->op, left, right); return ssa_emit_conv(proc, cmp, default_type(tv->type)); } break; |