aboutsummaryrefslogtreecommitdiff
path: root/types.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-10-08 21:10:36 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-10-08 21:10:36 -0400
commit839c1983a0dad0232da3ceda9c7c02a49715453c (patch)
tree955e588981f589b780257c2a8a6fade286f41876 /types.c
parent5103fde1c5e7e92f00801fb3a0e3662e436ee881 (diff)
Reduce padding needed for optional types and clean up some redundant
type padding
Diffstat (limited to 'types.c')
-rw-r--r--types.c58
1 files changed, 34 insertions, 24 deletions
diff --git a/types.c b/types.c
index a0e347ca..9407f957 100644
--- a/types.c
+++ b/types.c
@@ -398,6 +398,24 @@ PUREFUNC bool is_numeric_type(type_t *t)
return t->tag == IntType || t->tag == BigIntType || t->tag == NumType;
}
+PUREFUNC size_t unpadded_struct_size(type_t *t)
+{
+ arg_t *fields = Match(t, StructType)->fields;
+ size_t size = 0;
+ for (arg_t *field = fields; field; field = field->next) {
+ type_t *field_type = field->type;
+ if (field_type->tag == BoolType) {
+ size += 1; // Bit packing
+ } else {
+ size_t align = type_align(field_type);
+ if (align > 1 && size % align > 0)
+ size += align - (size % align); // Padding
+ size += type_size(field_type);
+ }
+ }
+ return size;
+}
+
PUREFUNC size_t type_size(type_t *t)
{
#pragma GCC diagnostic ignored "-Wswitch-default"
@@ -438,24 +456,22 @@ PUREFUNC size_t type_size(type_t *t)
case TYPE_IBITS8: return sizeof(OptionalInt8_t);
default: errx(1, "Invalid integer bit size");
}
- case StructType: return padded_type_size(nonnull) + 1;
+ case StructType: {
+ size_t size = unpadded_struct_size(nonnull);
+ size += sizeof(bool); // is_null flag
+ size_t align = type_align(nonnull);
+ if (align > 0 && (size % align) > 0)
+ size = (size + align) - (size % align);
+ return size;
+ }
default: return type_size(nonnull);
}
}
case StructType: {
- arg_t *fields = Match(t, StructType)->fields;
- size_t size = t->tag == StructType ? 0 : sizeof(void*);
- for (arg_t *field = fields; field; field = field->next) {
- type_t *field_type = field->type;
- if (field_type->tag == BoolType) {
- size += 1; // Bit packing
- } else {
- size_t align = type_align(field_type);
- if (align > 1 && size % align > 0)
- size += align - (size % align); // Padding
- size += type_size(field_type);
- }
- }
+ size_t size = unpadded_struct_size(t);
+ size_t align = type_align(t);
+ if (size > 0 && align > 0 && (size % align) > 0)
+ size = (size + align) - (size % align);
return size;
}
case EnumType: {
@@ -468,9 +484,12 @@ PUREFUNC size_t type_size(type_t *t)
if (size > max_size) max_size = size;
}
size_t size = sizeof(UnknownType); // generic enum
- if (max_align > 1 && size % max_align > 0)
+ if (max_align > 1 && size % max_align > 0) // Padding before first union field
size += max_align - (size % max_align);
size += max_size;
+ size_t align = MAX(__alignof__(UnknownType), max_align);
+ if (size % align > 0) // Padding after union
+ size += align - (size % align);
return size;
}
case TypeInfoType: return sizeof(TypeInfo_t);
@@ -545,15 +564,6 @@ PUREFUNC size_t type_align(type_t *t)
errx(1, "This should not be reachable");
}
-PUREFUNC size_t padded_type_size(type_t *t)
-{
- size_t size = type_size(t);
- size_t align = type_align(t);
- if (align > 1 && size % align > 0)
- size += align - (size % align); // Padding
- return size;
-}
-
type_t *get_field_type(type_t *t, const char *field_name)
{
t = value_type(t);