aboutsummaryrefslogtreecommitdiff
path: root/src/types.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/types.cpp')
-rw-r--r--src/types.cpp194
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;