summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c55
-rw-r--r--test.toc1
-rw-r--r--types.c6
-rw-r--r--types.h1
4 files changed, 32 insertions, 31 deletions
diff --git a/eval.c b/eval.c
index d6a29a8..01e8964 100644
--- a/eval.c
+++ b/eval.c
@@ -55,6 +55,31 @@ static size_t compiler_sizeof_builtin(BuiltinType b) {
return 0;
}
+static size_t compiler_alignof(Type *t);
+/* finds offsets and size */
+static void eval_struct_find_offsets(Type *t) {
+ assert(t->kind == TYPE_STRUCT);
+ if (!(t->struc->flags & STRUCT_DEF_FOUND_OFFSETS)) {
+ size_t bytes = 0;
+ size_t total_align = 0;
+ arr_foreach(t->struc->fields, Field, f) {
+ size_t falign = compiler_alignof(f->type);
+ if (falign > total_align)
+ total_align = falign;
+ /* align */
+ bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */
+ assert(bytes % falign == 0);
+ f->offset = bytes;
+ /* add size */
+ bytes += compiler_sizeof(f->type);
+ }
+ bytes += ((total_align - bytes) % total_align + total_align) % total_align; /* = -bytes mod align */
+ t->struc->size = bytes;
+ t->struc->align = total_align;
+ t->struc->flags |= STRUCT_DEF_FOUND_OFFSETS;
+ }
+}
+
static size_t compiler_alignof(Type *t) {
Value v;
assert(t->flags & TYPE_IS_RESOLVED);
@@ -82,12 +107,8 @@ static size_t compiler_alignof(Type *t) {
return sizeof v.pkg;
case TYPE_STRUCT: {
/* assume the align of a struct is (at most) the greatest align out of its children's */
- size_t align = 1;
- arr_foreach(t->struc->fields, Field, f) {
- size_t falign = compiler_alignof(f->type);
- if (falign > align) align = falign;
- }
- return align;
+ eval_struct_find_offsets(t);
+ return t->struc->align;
}
case TYPE_UNKNOWN:
case TYPE_EXPR:
@@ -97,28 +118,6 @@ static size_t compiler_alignof(Type *t) {
return 0;
}
-/* finds offsets and size */
-static void eval_struct_find_offsets(Type *t) {
- assert(t->kind == TYPE_STRUCT);
- if (!(t->struc->flags & STRUCT_DEF_FOUND_OFFSETS)) {
- size_t bytes = 0;
- arr_foreach(t->struc->fields, Field, f) {
- size_t falign = compiler_alignof(f->type);
- /* align */
- bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */
- assert(bytes % falign == 0);
- f->offset = bytes;
- /* add size */
- bytes += compiler_sizeof(f->type);
- }
- /* final align */
- size_t align = compiler_alignof(t);
- bytes += ((align - bytes) % align + align) % align; /* = -bytes mod align */
- t->struc->size = bytes;
- t->struc->flags |= STRUCT_DEF_FOUND_OFFSETS;
- }
-}
-
/* size of a type at compile time */
static size_t compiler_sizeof(Type *t) {
Value v;
diff --git a/test.toc b/test.toc
index e88affb..566bb72 100644
--- a/test.toc
+++ b/test.toc
@@ -18,5 +18,6 @@ main ::= fn() {
c:x = 7;
d:x = 18;
k : [5]struct {x: int; y: int;};
+ puti(#alignof(k));
puti(k[0].x);
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 66a31e9..778b9a4 100644
--- a/types.c
+++ b/types.c
@@ -1502,13 +1502,13 @@ static bool types_expr(Typer *tr, Expression *e) {
Expression *of = e->kind == EXPR_DSIZEOF ? e->dsizeof.of : e->dalignof.of;
if (!types_expr(tr, of))
return false;
- if (e->dsizeof.of->type.kind == TYPE_TYPE) {
+ if (of->type.kind == TYPE_TYPE) {
Value val;
if (!eval_expr(tr->evalr, of, &val))
return false;
- e->val.i64 = (I64)compiler_sizeof(val.type);
+ e->val.i64 = (I64)(e->kind == EXPR_DSIZEOF ? compiler_sizeof : compiler_alignof)(val.type);
} else {
- e->val.i64 = (I64)compiler_sizeof(&of->type);
+ e->val.i64 = (I64)(e->kind == EXPR_DSIZEOF ? compiler_sizeof : compiler_alignof)(&of->type);
}
e->kind = EXPR_VAL;
t->kind = TYPE_BUILTIN;
diff --git a/types.h b/types.h
index dc0d817..de945ed 100644
--- a/types.h
+++ b/types.h
@@ -387,6 +387,7 @@ typedef struct {
Location where;
U16 flags;
size_t size; /* size of this struct during compile time */
+ size_t align;
struct {
Identifier name;
IdentID id;