diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-10-08 15:16:13 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-10-08 15:16:13 +0100 |
| commit | 6424966b7ad6f85dc56d72cf623276f788a1a157 (patch) | |
| tree | 063d3063c885f331b71c51844f35a85d19af1f75 /src/types.cpp | |
| parent | 4e42d7df4303470dec5b3c354a9469699f6abf8d (diff) | |
Union tag stored as an integer
Diffstat (limited to 'src/types.cpp')
| -rw-r--r-- | src/types.cpp | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/src/types.cpp b/src/types.cpp index 85af08a9b..bb9e95667 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -118,7 +118,6 @@ struct TypeStruct { Array<Type *> variants; \ AstNode *node; \ Scope * scope; \ - Entity * union__type_info; \ i64 variant_block_size; \ i64 custom_align; \ }) \ @@ -1335,6 +1334,42 @@ bool is_type_cte_safe(Type *type) { return false; } +i64 union_variant_index(Type *u, Type *v) { + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + for_array(i, u->Union.variants) { + Type *vt = u->Union.variants[i]; + if (are_types_identical(v, vt)) { + return cast(i64)(i+1); + } + } + return 0; +} + +i64 union_tag_size(Type *u) { + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + u64 cl2 = ceil_log2(cast(u64)u->Union.variants.count); + i64 s = (next_pow2(cast(i64)cl2) + 7)/8; + return gb_clamp(s, 1, build_context.word_size); +} + +Type *union_tag_type(Type *u) { + i64 s = union_tag_size(u); + switch (s) { + case 1: return t_u8; + case 2: return t_u16; + case 4: return t_u32; + case 8: return t_u64; + case 16: return t_u128; + } + GB_PANIC("Invalid union_tag_size"); + return t_int; +} + + + enum ProcTypeOverloadKind { ProcOverload_Identical, // The types are identical @@ -1614,20 +1649,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } } else if (type->kind == Type_Union) { - if (field_name == "__type_info") { - Entity *e = type->Union.union__type_info; - if (e == nullptr) { - Entity *__type_info = make_entity_field(a, nullptr, make_token_ident(str_lit("__type_info")), t_type_info_ptr, false, -1); - type->Union.union__type_info = __type_info; - e = __type_info; - } - GB_ASSERT(e != nullptr); - selection_add_index(&sel, -1); // HACK(bill): Leaky memory - sel.entity = e; - - return sel; - } } else if (type->kind == Type_Struct) { for_array(i, type->Struct.fields) { Entity *f = type->Struct.fields[i]; @@ -1854,7 +1876,9 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { if (t->Union.custom_align > 0) { return gb_clamp(t->Union.custom_align, 1, build_context.max_align); } - i64 max = build_context.word_size; + + + i64 max = union_tag_size(t); for_array(i, t->Union.variants) { Type *variant = t->Union.variants[i]; type_path_push(path, variant); |