aboutsummaryrefslogtreecommitdiff
path: root/src/types.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/types.c')
-rw-r--r--src/types.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/types.c b/src/types.c
index 5138164..008af10 100644
--- a/src/types.c
+++ b/src/types.c
@@ -107,6 +107,7 @@ static char *data_type_to_str(Type *type)
case TYPE_CHAR: return "char";
case TYPE_ANY: return "<@>";
case TYPE_STRUCT: return type->struct_name;
+ case TYPE_UNION: return type->struct_name;
default: assert(false && "Unreachable");
}
}
@@ -133,19 +134,21 @@ char *type_to_str(Type *type)
i64 push_field(Type *type, char *field_name, Type *field_type)
{
- assert(type->type == TYPE_STRUCT);
+ assert(type->type == TYPE_STRUCT || type->type == TYPE_UNION);
+ bool is_union = type->type == TYPE_UNION;
+
type->fields.type = realloc(type->fields.type, sizeof(Type *) * (type->fields.num_fields + 1));
type->fields.offset = realloc(type->fields.offset, sizeof(i64) * (type->fields.num_fields + 1));
type->fields.name = realloc(type->fields.name, sizeof(char *) * (type->fields.num_fields + 1));
i64 field_size = size_for_type(field_type);
i64 offset_factor = i64min(field_size, 8);
- i64 offset = align_up(type->fields.size, offset_factor);
+ i64 offset = is_union ? 0 : align_up(type->fields.size, offset_factor);
type->fields.type[type->fields.num_fields] = field_type;
type->fields.offset[type->fields.num_fields] = offset;
type->fields.name[type->fields.num_fields] = field_name;
- type->fields.size = offset + field_size;
+ type->fields.size = is_union ? i64max(field_size, type->fields.size) : offset + field_size;
type->fields.num_fields++;
return offset;
@@ -153,7 +156,7 @@ i64 push_field(Type *type, char *field_name, Type *field_type)
i64 find_field_index(Type *type, char *field_name)
{
- assert(type->type == TYPE_STRUCT);
+ assert(type->type == TYPE_STRUCT || type->type == TYPE_UNION);
for (int i = 0; i < type->fields.num_fields; i++) {
if (strcmp(type->fields.name[i], field_name) == 0)
return i;