diff options
Diffstat (limited to 'rt_struct.c')
-rw-r--r-- | rt_struct.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/rt_struct.c b/rt_struct.c new file mode 100644 index 0000000..314407c --- /dev/null +++ b/rt_struct.c @@ -0,0 +1,49 @@ +#include <stdlib.h> +#include <string.h> +#include "macros.h" +#include "rt_struct.h" + +static int is_root_type(rts_type_tag tag) { + return tag != TAG_STRUCT && tag != TAG_UNION; +} + +int create_rts(rts_type *type) { + if (type == NULL) { + return 1; + } + + if (is_root_type(type->tag)) { + return 0; + } + + if (type->members == NULL || type->members[0] == NULL) { + return 1; + } else { + size_t offset = 0; + size_t max_align = 0; + size_t remainder = 0; + size_t padding = 0; + rts_member **members = type->members; + for (int i = 0; members[i] != NULL; ++i) { + rts_type *member_type = members[i]->type; + if (create_rts(member_type)) { + return 1; + } else { + const size_t align = member_type->alignment; + max_align = max(max_align, align); + if (type->tag == TAG_STRUCT) { + remainder = offset % align; + padding = (remainder) ? align - remainder : 0; + offset += padding; + type->offsets[i] = offset; + offset += member_type->size; + } + } + } + type->alignment = max_align; + remainder = offset % max_align; + padding = (remainder) ? max_align - remainder : 0; + type->size = offset + padding; + return 0; + } +} |