#include #include #include "macros.h" #include "rt_struct.h" static int is_root_type(rts_type_tag tag) { return tag != TAG_STRUCT && tag != TAG_UNION; } static int member_is_ptr(rts_member_type type) { return type >= MBR_PTR && type <= MBR_PTR_ARRAY_NULL; } static int member_is_fixed_array(rts_member_type type) { return type == MBR_ARRAY || type == MBR_PTR_ARRAY; } static size_t member_size(rts_member *member) { const rts_type *type = (member_is_ptr(member->mbr_type)) ? &RTS_TYPE_POINTER : member->type; size_t size = type->size; if (member_is_fixed_array(member->mbr_type)) { for (int i = 0; i < member->dim_count && member->dim_sizes[i]; ++i) { size *= member->dim_sizes[i]; } } return size; } 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) { if (create_rts(members[i]->type)) { return 1; } else { const rts_type *member_type = (member_is_ptr(members[i]->mbr_type)) ? &RTS_TYPE_POINTER : members[i]->type; 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_size(members[i]); } } } type->alignment = max_align; remainder = offset % max_align; padding = (remainder) ? max_align - remainder : 0; type->size = offset + padding; return 0; } }