summaryrefslogtreecommitdiff
path: root/rt_struct.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2022-08-08 19:23:30 -0300
committermrb0nk500 <b0nk@b0nk.xyz>2022-08-09 10:57:41 -0300
commit85557e4c906bf66a8c3abc0c91aa5c9e65f5e033 (patch)
treed82dba26c435c3e38c2839a3a96b41d628c1f40a /rt_struct.c
parent11cb1d1bfb6bd7e306a4bff35fe82bb937a752e0 (diff)
rt_struct: Create `rt_struct.{c,h}`, and add `create_rts()`
This is a simple implementation of runtime structs, which was taken from lavignes' librts, and modified to make it alot easier to work with. Link to librts: https://github.com/lavignes/librts
Diffstat (limited to 'rt_struct.c')
-rw-r--r--rt_struct.c49
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;
+ }
+}