diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-07-10 22:59:23 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-07-10 22:59:23 +0100 |
| commit | ba5050ac7c2eb116b8989b7d387e67eb79eec62a (patch) | |
| tree | d36d5cc1c9c6e31c88b27109792f21ca21e8a23f /src/types.cpp | |
| parent | d936ca1ea003f82e0fda330cbad1f5bcf4387df2 (diff) | |
Compiler Internal Changes: TypeRecord_Union -> Type_Union
Diffstat (limited to 'src/types.cpp')
| -rw-r--r-- | src/types.cpp | 262 |
1 files changed, 113 insertions, 149 deletions
diff --git a/src/types.cpp b/src/types.cpp index 5613d556f..52a14e352 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -73,7 +73,7 @@ enum TypeRecordKind { TypeRecord_Struct, TypeRecord_RawUnion, - TypeRecord_Union, // Tagged + // TypeRecord_Union, // Tagged // TypeRecord_Enum, TypeRecord_Count, @@ -93,13 +93,13 @@ struct TypeRecord { Scope * scope; // Entity_TypeName - union - Type ** variants; - i32 variant_count; - Entity * union__tag; - i64 variant_block_size; // NOTE(bill): Internal use only + // Type ** variants; + // i32 variant_count; + // Entity * union__tag; + // i64 variant_block_size; // NOTE(bill): Internal use only - Type * variant_parent; - i32 variant_index; + // Type * variant_parent; + // i32 variant_index; i64 * offsets; bool are_offsets_set; @@ -137,6 +137,17 @@ struct TypeRecord { Entity * min_value; \ Entity * max_value; \ }) \ + TYPE_KIND(Union, struct { \ + Type ** variants; \ + i32 variant_count; \ + AstNode *node; \ + Scope * scope; \ + Entity * union__tag; \ + i64 variant_block_size; \ + Type * variant_parent; \ + i32 variant_index; \ + i64 custom_align; \ + }) \ TYPE_KIND(Named, struct { \ String name; \ Type * base; \ @@ -539,8 +550,7 @@ Type *make_type_struct(gbAllocator a) { } Type *make_type_union(gbAllocator a) { - Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_Union; + Type *t = alloc_type(a, Type_Union); return t; } @@ -867,14 +877,7 @@ bool is_type_struct(Type *t) { } bool is_type_union(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_Union); -} -bool is_type_variant(Type *t) { - t = base_type(t); - if (t->kind == Type_Record) { - return t->Record.kind == TypeRecord_Struct && t->Record.variant_parent != nullptr; - } - return false; + return t->kind == Type_Union; } bool is_type_raw_union(Type *t) { @@ -1002,14 +1005,17 @@ bool is_type_polymorphic(Type *t) { } return false; } - case Type_Record: - for (isize i = 0; i < t->Record.field_count; i++) { - if (is_type_polymorphic(t->Record.fields[i]->type)) { + break; + case Type_Union: + for (isize i = 1; i < t->Union.variant_count; i++) { + if (is_type_polymorphic(t->Union.variants[i])) { return true; } } - for (isize i = 1; i < t->Record.variant_count; i++) { - if (is_type_polymorphic(t->Record.variants[i])) { + break; + case Type_Record: + for (isize i = 0; i < t->Record.field_count; i++) { + if (is_type_polymorphic(t->Record.fields[i]->type)) { return true; } } @@ -1052,11 +1058,9 @@ bool type_has_nil(Type *t) { case Type_DynamicArray: case Type_Map: return true; + case Type_Union: + return true; case Type_Record: - switch (t->Record.kind) { - case TypeRecord_Union: - return true; - } return false; } return false; @@ -1140,15 +1144,28 @@ bool are_types_identical(Type *x, Type *y) { case Type_Enum: return x == y; // NOTE(bill): All enums are unique + case Type_Union: + if (y->kind == Type_Union) { + if (x->Union.variant_count == y->Union.variant_count && + x->Union.custom_align == y->Union.custom_align) { + // NOTE(bill): zeroth variant is nullptr + for (isize i = 1; i < x->Union.variant_count; i++) { + if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) { + return false; + } + } + return true; + } + } + break; + case Type_Record: if (y->kind == Type_Record) { if (x->Record.kind == y->Record.kind) { switch (x->Record.kind) { case TypeRecord_Struct: case TypeRecord_RawUnion: - case TypeRecord_Union: if (x->Record.field_count == y->Record.field_count && - x->Record.variant_count == y->Record.variant_count && x->Record.is_packed == y->Record.is_packed && x->Record.is_ordered == y->Record.is_ordered && x->Record.custom_align == y->Record.custom_align) { @@ -1168,12 +1185,6 @@ bool are_types_identical(Type *x, Type *y) { return false; } } - // NOTE(bill): zeroth variant is nullptr - for (isize i = 1; i < x->Record.variant_count; i++) { - if (!are_types_identical(x->Record.variants[i], y->Record.variants[i])) { - return false; - } - } return true; } break; @@ -1597,6 +1608,14 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n } } + } else if (type->Record.kind == Type_Union) { + if (field_name == "__tag") { + Entity *e = type->Union.union__tag; + GB_ASSERT(e != nullptr); + selection_add_index(&sel, -1); // HACK(bill): Leaky memory + sel.entity = e; + return sel; + } } else if (type->kind == Type_Record) { for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; @@ -1625,15 +1644,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.index.count = prev_count; } } - if (type->Record.kind == TypeRecord_Union) { - if (field_name == "__tag") { - Entity *e = type->Record.union__tag; - GB_ASSERT(e != nullptr); - selection_add_index(&sel, -1); // HACK(bill): Leaky memory - sel.entity = e; - return sel; - } - } } else if (type->kind == Type_BitField) { for (isize i = 0; i < type->BitField.field_count; i++) { Entity *f = type->BitField.fields[i]; @@ -1828,6 +1838,24 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Enum: return type_align_of_internal(allocator, t->Enum.base_type, path); + case Type_Union: { + i64 max = build_context.word_size; + // NOTE(bill): field zero is null + for (isize i = 1; i < t->Union.variant_count; i++) { + Type *variant = t->Union.variants[i]; + type_path_push(path, variant); + if (path->failure) { + return FAILURE_ALIGNMENT; + } + i64 align = type_align_of_internal(allocator, variant, path); + type_path_pop(path); + if (max < align) { + max = align; + } + } + return max; + } break; + case Type_Record: { switch (t->Record.kind) { case TypeRecord_Struct: @@ -1854,35 +1882,6 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return max; } break; - case TypeRecord_Union: { - i64 max = 1; - if (t->Record.field_count > 0) { - Type *field_type = t->Record.fields[0]->type; - type_path_push(path, field_type); - i64 align = type_align_of_internal(allocator, field_type, path); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - type_path_pop(path); - if (max < align) { - max = align; - } - } - // NOTE(bill): field zero is null - for (isize i = 1; i < t->Record.variant_count; i++) { - Type *variant = t->Record.variants[i]; - type_path_push(path, variant); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - i64 align = type_align_of_internal(allocator, variant, path); - type_path_pop(path); - if (max < align) { - max = align; - } - } - return max; - } break; case TypeRecord_RawUnion: { i64 max = 1; for (isize i = 0; i < t->Record.field_count; i++) { @@ -1947,14 +1946,7 @@ bool type_set_offsets(gbAllocator allocator, Type *t) { t->Record.are_offsets_set = true; return true; } - } else if (is_type_union(t)) { - if (!t->Record.are_offsets_set) { - t->Record.are_offsets_being_processed = true; - t->Record.offsets = type_set_offsets_of(allocator, t->Record.fields, t->Record.field_count, false); - t->Record.are_offsets_set = true; - return true; - } - } else if (is_type_tuple(t)) { + } else if (is_type_tuple(t)) { if (!t->Tuple.are_offsets_set) { t->Record.are_offsets_being_processed = true; t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, t->Tuple.variable_count, false); @@ -2080,6 +2072,36 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Enum: return type_size_of_internal(allocator, t->Enum.base_type, path); + case Type_Union: { + i64 align = type_align_of_internal(allocator, t, path); + if (path->failure) { + return FAILURE_SIZE; + } + + i64 max = 0; + isize variant_count = t->Union.variant_count; + + i64 field_size = max; + + for (isize i = 1; i < variant_count; i++) { + Type *variant_type = t->Union.variants[i]; + i64 size = type_size_of_internal(allocator, variant_type, path); + if (max < size) { + max = size; + } + } + + // NOTE(bill): Align to int + i64 size = align_formula(max, build_context.word_size); + // NOTE(bill): Calculate the padding between the common fields and the tag + t->Union.variant_block_size = size - field_size; + + size += type_size_of(allocator, t_int); + size = align_formula(size, align); + return size; + } break; + + case Type_Record: { switch (t->Record.kind) { @@ -2101,52 +2123,6 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return align_formula(size, align); } break; - case TypeRecord_Union: { - i64 align = type_align_of_internal(allocator, t, path); - if (path->failure) { - return FAILURE_SIZE; - } - - i64 max = 0; - isize field_count = t->Record.field_count; - isize variant_count = t->Record.variant_count; - - // Check for recursive types - for (isize i = 0; i < field_count; i++) { - i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path); - if (path->failure) { - return FAILURE_SIZE; - } - } - // NOTE(bill): Zeroth field is invalid - type_set_offsets(allocator, t); - - if (field_count > 0) { - Type *end_type = t->Record.fields[field_count-1]->type; - i64 end_offset = t->Record.offsets[field_count-1]; - i64 end_size = type_size_of_internal(allocator, end_type, path); - max = end_offset + end_size ; - } - i64 field_size = max; - - for (isize i = 1; i < variant_count; i++) { - Type *variant_type = t->Record.variants[i]; - i64 size = type_size_of_internal(allocator, variant_type, path); - if (max < size) { - max = size; - } - } - - // NOTE(bill): Align to int - i64 size = align_formula(max, build_context.word_size); - // NOTE(bill): Calculate the padding between the common fields and the tag - t->Record.variant_block_size = size - field_size; - - size += type_size_of(allocator, t_int); - size = align_formula(size, align); - return size; - } break; - case TypeRecord_RawUnion: { i64 count = t->Record.field_count; i64 align = type_align_of_internal(allocator, t, path); @@ -2185,7 +2161,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) { t = base_type(t); - if (t->kind == Type_Record && (t->Record.kind == TypeRecord_Struct || t->Record.kind == TypeRecord_Union)) { + if (t->kind == Type_Record && (t->Record.kind == TypeRecord_Struct)) { type_set_offsets(allocator, t); if (gb_is_between(index, 0, t->Record.field_count-1)) { return t->Record.offsets[index]; @@ -2342,6 +2318,16 @@ gbString write_type_to_string(gbString str, Type *type) { str = gb_string_appendc(str, "}"); break; + case Type_Union: + str = gb_string_appendc(str, "union{"); + for (isize i = 1; i < type->Union.variant_count; i++) { + Type *t = type->Union.variants[i]; + if (i > 1) str = gb_string_appendc(str, ", "); + str = write_type_to_string(str, t); + } + str = gb_string_appendc(str, "}"); + break; + case Type_Record: { switch (type->Record.kind) { case TypeRecord_Struct: @@ -2366,28 +2352,6 @@ gbString write_type_to_string(gbString str, Type *type) { str = gb_string_appendc(str, "}"); break; - case TypeRecord_Union: - str = gb_string_appendc(str, "union{"); - for (isize i = 0; i < type->Record.field_count; i++) { - Entity *f = type->Record.fields[i]; - GB_ASSERT(f->kind == Entity_Variable); - if (i > 0) { - str = gb_string_appendc(str, ", "); - } - str = gb_string_append_length(str, f->token.string.text, f->token.string.len); - str = gb_string_appendc(str, ": "); - str = write_type_to_string(str, f->type); - } - for (isize i = 1; i < type->Record.variant_count; i++) { - Type *t = type->Record.variants[i]; - if (i > 1 || type->Record.field_count > 1) { - str = gb_string_appendc(str, ", "); - } - str = write_type_to_string(str, t); - } - str = gb_string_appendc(str, "}"); - break; - case TypeRecord_RawUnion: str = gb_string_appendc(str, "raw_union{"); for (isize i = 0; i < type->Record.field_count; i++) { |