diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-07-18 19:24:45 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-07-18 19:24:45 +0100 |
| commit | 59fb7b020a5e0bd2d23daab0f74e9cfa23420afc (patch) | |
| tree | 435bd10ec767d4bdf56bfc3d232c0c9debea18d8 /src/types.cpp | |
| parent | 65f079ebc474f9decc7afb222630c04b4da32690 (diff) | |
Merge `raw_union` into `struct` as a memory layout tag `#raw_union`
Diffstat (limited to 'src/types.cpp')
| -rw-r--r-- | src/types.cpp | 194 |
1 files changed, 81 insertions, 113 deletions
diff --git a/src/types.cpp b/src/types.cpp index 3c9d99728..3fe9029d8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -68,17 +68,7 @@ struct BasicType { String name; }; -enum TypeRecordKind { - TypeRecord_Invalid, - - TypeRecord_Struct, - TypeRecord_RawUnion, - - TypeRecord_Count, -}; - struct TypeRecord { - TypeRecordKind kind; // All record types // Theses are arrays @@ -94,6 +84,7 @@ struct TypeRecord { bool are_offsets_being_processed; bool is_packed; bool is_ordered; + bool is_raw_union; bool is_polymorphic; bool is_poly_specialized; Type * polymorphic_params; // Type_Tuple @@ -523,7 +514,6 @@ Type *make_type_slice(gbAllocator a, Type *elem) { Type *make_type_struct(gbAllocator a) { Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_Struct; return t; } @@ -532,12 +522,6 @@ Type *make_type_union(gbAllocator a) { return t; } -Type *make_type_raw_union(gbAllocator a) { - Type *t = alloc_type(a, Type_Record); - t->Record.kind = TypeRecord_RawUnion; - return t; -} - Type *make_type_enum(gbAllocator a) { Type *t = alloc_type(a, Type_Enum); return t; @@ -847,7 +831,7 @@ Type *base_complex_elem_type(Type *t) { bool is_type_struct(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct); + return (t->kind == Type_Record && !t->Record.is_raw_union); } bool is_type_union(Type *t) { t = base_type(t); @@ -856,7 +840,7 @@ bool is_type_union(Type *t) { bool is_type_raw_union(Type *t) { t = base_type(t); - return (t->kind == Type_Record && t->Record.kind == TypeRecord_RawUnion); + return (t->kind == Type_Record && t->Record.is_raw_union); } bool is_type_enum(Type *t) { t = base_type(t); @@ -932,8 +916,7 @@ bool is_type_indexable(Type *t) { bool is_type_polymorphic_struct(Type *t) { t = base_type(t); - if (t->kind == Type_Record && - t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record) { return t->Record.is_polymorphic; } return false; @@ -941,8 +924,7 @@ bool is_type_polymorphic_struct(Type *t) { bool is_type_polymorphic_struct_specialized(Type *t) { t = base_type(t); - if (t->kind == Type_Record && - t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record) { return t->Record.is_polymorphic && t->Record.is_poly_specialized; } return false; @@ -1158,34 +1140,28 @@ bool are_types_identical(Type *x, Type *y) { 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: - if (x->Record.field_count == y->Record.field_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) { - // TODO(bill); Fix the custom alignment rule - for (isize i = 0; i < x->Record.field_count; i++) { - Entity *xf = x->Record.fields[i]; - Entity *yf = y->Record.fields[i]; - if (!are_types_identical(xf->type, yf->type)) { - return false; - } - if (xf->token.string != yf->token.string) { - return false; - } - bool xf_is_using = (xf->flags&EntityFlag_Using) != 0; - bool yf_is_using = (yf->flags&EntityFlag_Using) != 0; - if (xf_is_using ^ yf_is_using) { - return false; - } - } - return true; + if (x->Record.is_raw_union == y->Record.is_raw_union && + x->Record.field_count == y->Record.field_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) { + // TODO(bill); Fix the custom alignment rule + for (isize i = 0; i < x->Record.field_count; i++) { + Entity *xf = x->Record.fields[i]; + Entity *yf = y->Record.fields[i]; + if (!are_types_identical(xf->type, yf->type)) { + return false; + } + if (xf->token.string != yf->token.string) { + return false; + } + bool xf_is_using = (xf->flags&EntityFlag_Using) != 0; + bool yf_is_using = (yf->flags&EntityFlag_Using) != 0; + if (xf_is_using ^ yf_is_using) { + return false; } - break; } + return true; } } break; @@ -1310,7 +1286,7 @@ bool is_type_cte_safe(Type *type) { return false; case Type_Record: { - if (type->Record.kind != TypeRecord_Struct) { + if (type->Record.is_raw_union) { return false; } for (isize i = 0; i < type->Record.field_count; i++) { @@ -1619,7 +1595,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n return lookup_field_with_selection(a, specialized, field_name, is_type, sel); } - } else if (type->Record.kind == Type_Union) { + } else if (type->kind == Type_Union) { if (field_name == "__tag") { Entity *e = type->Union.union__tag; GB_ASSERT(e != nullptr); @@ -1868,8 +1844,22 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } break; case Type_Record: { - switch (t->Record.kind) { - case TypeRecord_Struct: + if (t->Record.is_raw_union) { + i64 max = 1; + for (isize i = 0; i < t->Record.field_count; i++) { + Type *field_type = t->Record.fields[i]->type; + type_path_push(path, field_type); + if (path->failure) { + return FAILURE_ALIGNMENT; + } + i64 align = type_align_of_internal(allocator, field_type, path); + type_path_pop(path); + if (max < align) { + max = align; + } + } + return max; + } else { if (t->Record.custom_align > 0) { return gb_clamp(t->Record.custom_align, 1, build_context.max_align); } @@ -1892,23 +1882,6 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } return max; } - break; - case TypeRecord_RawUnion: { - i64 max = 1; - for (isize i = 0; i < t->Record.field_count; i++) { - Type *field_type = t->Record.fields[i]->type; - type_path_push(path, field_type); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - i64 align = type_align_of_internal(allocator, field_type, path); - type_path_pop(path); - if (max < align) { - max = align; - } - } - return max; - } break; } } break; @@ -1927,10 +1900,14 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { return gb_clamp(next_pow2(type_size_of_internal(allocator, t, path)), 1, build_context.word_size); } -i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_count, bool is_packed) { +i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_count, bool is_packed, bool is_raw_union) { i64 *offsets = gb_alloc_array(allocator, i64, field_count); i64 curr_offset = 0; - if (is_packed) { + if (is_raw_union) { + for (isize i = 0; i < field_count; i++) { + offsets[i] = 0; + } + } else if (is_packed) { for (isize i = 0; i < field_count; i++) { i64 size = type_size_of(allocator, fields[i]->type); offsets[i] = curr_offset; @@ -1950,17 +1927,17 @@ i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_cou bool type_set_offsets(gbAllocator allocator, Type *t) { t = base_type(t); - if (is_type_struct(t)) { + if (t->kind == Type_Record) { 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, t->Record.is_packed); + t->Record.offsets = type_set_offsets_of(allocator, t->Record.fields, t->Record.field_count, t->Record.is_packed, t->Record.is_raw_union); t->Record.are_offsets_set = true; return true; } } 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); + t->Tuple.offsets = type_set_offsets_of(allocator, t->Tuple.variables, t->Tuple.variable_count, false, false); t->Tuple.are_offsets_set = true; return true; } @@ -2114,9 +2091,22 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Record: { - switch (t->Record.kind) { - - case TypeRecord_Struct: { + if (t->Record.is_raw_union) { + i64 count = t->Record.field_count; + i64 align = type_align_of_internal(allocator, t, path); + if (path->failure) { + return FAILURE_SIZE; + } + i64 max = 0; + for (isize i = 0; i < count; i++) { + i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path); + if (max < size) { + max = size; + } + } + // TODO(bill): Is this how it should work? + return align_formula(max, align); + } else { i64 count = t->Record.field_count; if (count == 0) { return 0; @@ -2132,24 +2122,6 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { type_set_offsets(allocator, t); i64 size = t->Record.offsets[count-1] + type_size_of_internal(allocator, t->Record.fields[count-1]->type, path); return align_formula(size, align); - } break; - - case TypeRecord_RawUnion: { - i64 count = t->Record.field_count; - i64 align = type_align_of_internal(allocator, t, path); - if (path->failure) { - return FAILURE_SIZE; - } - i64 max = 0; - for (isize i = 0; i < count; i++) { - i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path); - if (max < size) { - max = size; - } - } - // TODO(bill): Is this how it should work? - return align_formula(max, align); - } break; } } break; @@ -2172,7 +2144,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)) { + if (t->kind == Type_Record && !t->Record.is_raw_union) { type_set_offsets(allocator, t); if (gb_is_between(index, 0, t->Record.field_count-1)) { return t->Record.offsets[index]; @@ -2221,7 +2193,7 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s isize index = sel.index[i]; t = base_type(t); offset += type_offset_of(allocator, t, index); - if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) { + if (t->kind == Type_Record && !t->Record.is_raw_union) { t = t->Record.fields[index]->type; } else { // NOTE(bill): No need to worry about custom types, just need the alignment @@ -2339,16 +2311,8 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_Record: { - switch (type->Record.kind) { - case TypeRecord_Struct: - str = gb_string_appendc(str, "struct"); - if (type->Record.is_packed) { - str = gb_string_appendc(str, " #packed"); - } - if (type->Record.is_ordered) { - str = gb_string_appendc(str, " #ordered"); - } - str = gb_string_appendc(str, " {"); + if (type->Record.is_raw_union) { + str = gb_string_appendc(str, "raw_union{"); for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; GB_ASSERT(f->kind == Entity_Variable); @@ -2360,10 +2324,15 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, f->type); } str = gb_string_appendc(str, "}"); - break; - - case TypeRecord_RawUnion: - str = gb_string_appendc(str, "raw_union{"); + } else { + str = gb_string_appendc(str, "struct"); + if (type->Record.is_packed) { + str = gb_string_appendc(str, " #packed"); + } + if (type->Record.is_ordered) { + str = gb_string_appendc(str, " #ordered"); + } + str = gb_string_appendc(str, " {"); for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; GB_ASSERT(f->kind == Entity_Variable); @@ -2375,7 +2344,6 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, f->type); } str = gb_string_appendc(str, "}"); - break; } } break; |