aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-04-12 02:19:23 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-04-12 02:19:23 +0300
commite1f17535a043b55ce34de4d7583928d8c94bb71a (patch)
tree256299aeb970730e56a48e6ad72ac82e848a14d1 /src/ast.c
parent7294673a9889f968eef86930d4e09f47070439fc (diff)
downloadek-e1f17535a043b55ce34de4d7583928d8c94bb71a.tar.gz
ek-e1f17535a043b55ce34de4d7583928d8c94bb71a.zip
start work on struct handling
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/ast.c b/src/ast.c
index b3cf408..df016a8 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -91,6 +91,7 @@ static struct type *create_empty_type()
struct type *n = calloc(1, sizeof(struct type));
/* just to be safe */
n->k = TYPE_VOID;
+ n->size = -1;
vect_append(struct ast *, types, &n);
return n;
}
@@ -379,6 +380,11 @@ struct ast *clone_ast(struct ast *n)
new->v = n->v;
new->f = n->f;
+ /* unsure if this should be a separate step maybe? Generally this is
+ * unwanted, but I might run into exceptions and then it's more
+ * difficult to rebuild the init/actual state... */
+ ast_clear_flags(new, AST_FLAG_INIT | AST_FLAG_ACTUAL);
+
if (n->t)
new->t = clone_type_list(n->t);
@@ -658,3 +664,67 @@ int equiv_type_lists(struct type *t1, struct type *t2)
return 1;
}
+
+size_t align3k(size_t o)
+{
+ size_t rem = o % 3;
+ if (rem)
+ o += rem;
+
+ return o;
+}
+
+static size_t struct_size(struct type *t)
+{
+ if (t->size != -1)
+ return t->size;
+
+ size_t size = 0;
+ foreach_node(n, struct_body(t->d)) {
+ if (n->k != AST_VAR_DEF)
+ continue;
+
+ size_t sz = type_size(n->t);
+ if (sz > 2)
+ size = align3k(size);
+
+ size += sz;
+ }
+
+ t->size = size;
+ return size;
+}
+
+size_t type_size(struct type *t)
+{
+ switch (t->k) {
+ case TYPE_I9: return 1;
+ case TYPE_I27: return 3;
+ case TYPE_PTR: return 3;
+ case TYPE_STRUCT: return struct_size(t);
+ default:
+ }
+
+ assert(0 && "unhandled type to get size of");
+ abort();
+}
+
+size_t type_offsetof(struct type *t, char *m)
+{
+ assert(t->k == TYPE_STRUCT);
+
+ size_t offset = 0;
+ foreach_node(n, struct_body(t->d)) {
+ if (n->k != AST_VAR_DEF)
+ continue;
+
+ if (same_id(var_id(n), m))
+ break;
+
+ size_t sz = type_size(n->t);
+ if (sz > 2)
+ offset = align3k(offset);
+ }
+
+ return offset;
+}