aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--main.c74
-rw-r--r--tests/028.sh90
2 files changed, 160 insertions, 4 deletions
diff --git a/main.c b/main.c
index dad36c1..5e7a8d4 100644
--- a/main.c
+++ b/main.c
@@ -333,6 +333,9 @@ int type_is_unsized_type(TYPE* ty) {
return ty->kind != TY_VOID;
}
+int type_sizeof_struct(TYPE* ty);
+int type_alignof_struct(TYPE* ty);
+
int type_sizeof(TYPE* ty) {
if (!type_is_unsized_type(ty)) {
fatal_error("type_sizeof: type size cannot be determined");
@@ -347,7 +350,25 @@ int type_sizeof(TYPE* ty) {
} else if (ty->kind == TY_LONG) {
return 8;
} else {
- todo();
+ return type_sizeof_struct(ty);
+ }
+}
+
+int type_alignof(TYPE* ty) {
+ if (!type_is_unsized_type(ty)) {
+ fatal_error("type_alignof: type size cannot be determined");
+ }
+
+ if (ty->kind == TY_PTR) {
+ return 8;
+ } else if (ty->kind == TY_CHAR) {
+ return 1;
+ } else if (ty->kind == TY_INT) {
+ return 4;
+ } else if (ty->kind == TY_LONG) {
+ return 8;
+ } else {
+ return type_alignof_struct(ty);
}
}
@@ -458,6 +479,38 @@ AST* ast_new_assign_expr(int op, AST* lhs, AST* rhs) {
return e;
}
+int type_sizeof_struct(TYPE* ty) {
+ int next_offset = 0;
+ int struct_align = 0;
+
+ AST* member = ty->members->next;
+ while (member) {
+ int size = type_sizeof(member->ty);
+ int align = type_alignof(member->ty);
+
+ if (next_offset % align != 0) {
+ int padding = align - next_offset % align;
+ next_offset += padding;
+ }
+ next_offset += size;
+ if (struct_align < align) {
+ struct_align = align;
+ }
+
+ member = member->next;
+ }
+ if (next_offset % struct_align != 0) {
+ int padding = struct_align - next_offset % struct_align;
+ next_offset += padding;
+ }
+ return next_offset;
+}
+
+int type_alignof_struct(TYPE* ty) {
+ todo();
+ return 0;
+}
+
#define LVAR_MAX 32
typedef struct LVar {
@@ -981,12 +1034,25 @@ AST* parse_struct_members(PARSER* p) {
AST* parse_struct_decl_or_def(PARSER* p) {
expect(p, TK_K_STRUCT);
char* name = parse_ident(p);
- p->structs[p->n_structs].name = name;
- p->n_structs += 1;
+ int struct_index;
+ for (struct_index = 0; struct_index < p->n_structs; struct_index++) {
+ if (strcmp(name, p->structs[struct_index].name) == 0) {
+ break;
+ }
+ }
+ if (struct_index == p->n_structs) {
+ p->structs[struct_index].name = name;
+ p->n_structs += 1;
+ }
if (peek_token(p)->kind == TK_SEMICOLON) {
next_token(p);
return ast_new(AST_STRUCT_DECL);
}
+ if (p->structs[struct_index].node1) {
+ char buf[1024];
+ sprintf(buf, "parse_struct_decl_or_def: struct %s redefined", name);
+ fatal_error(buf);
+ }
expect(p, TK_BRACE_L);
AST* members = parse_struct_members(p);
expect(p, TK_BRACE_R);
@@ -994,7 +1060,7 @@ AST* parse_struct_decl_or_def(PARSER* p) {
AST* s = ast_new(AST_STRUCT_DEF);
s->name = name;
s->node1 = members;
- p->structs[p->n_structs - 1].node1 = members;
+ p->structs[struct_index].node1 = members;
return s;
}
diff --git a/tests/028.sh b/tests/028.sh
new file mode 100644
index 0000000..f5f7a6d
--- /dev/null
+++ b/tests/028.sh
@@ -0,0 +1,90 @@
+set -e
+
+cat <<'EOF' > expected
+sizeof(struct Token) = 16
+sizeof(struct Define) = 16
+sizeof(struct Type) = 24
+sizeof(struct AstNode) = 128
+sizeof(struct LVar) = 16
+sizeof(struct Func) = 16
+sizeof(struct Parser) = 64
+sizeof(struct CodeGen) = 16
+EOF
+bash ../../test_diff.sh <<'EOF'
+struct Token {
+ int kind;
+ char* value;
+};
+
+struct Define {
+ char* from;
+ struct Token* to;
+};
+
+struct AstNode;
+
+struct Type {
+ int kind;
+ struct Type* to;
+ struct AstNode* members;
+};
+
+struct AstNode {
+ int kind;
+ struct AstNode* next;
+ struct AstNode* last;
+ char* name;
+ struct AstNode* func_params;
+ struct AstNode* func_body;
+ int int_value;
+ struct AstNode* expr1;
+ struct AstNode* expr2;
+ struct AstNode* expr3;
+ int op;
+ struct Type* ty;
+ int var_index;
+ struct AstNode* node1;
+ struct AstNode* node2;
+ char** str_literals;
+};
+
+struct LVar {
+ char* name;
+ struct Type* ty;
+};
+
+struct Func {
+ char* name;
+ struct Type* ty;
+};
+
+struct Parser {
+ struct Token* tokens;
+ int pos;
+ struct LVar* locals;
+ int n_locals;
+ struct Func* funcs;
+ int n_funcs;
+ char** str_literals;
+ int n_str_literals;
+};
+
+struct CodeGen {
+ int next_label;
+ int* loop_labels;
+};
+
+int printf();
+
+int main() {
+ printf("sizeof(struct Token) = %d\n", sizeof(struct Token));
+ printf("sizeof(struct Define) = %d\n", sizeof(struct Define));
+ printf("sizeof(struct Type) = %d\n", sizeof(struct Type));
+ printf("sizeof(struct AstNode) = %d\n", sizeof(struct AstNode));
+ printf("sizeof(struct LVar) = %d\n", sizeof(struct LVar));
+ printf("sizeof(struct Func) = %d\n", sizeof(struct Func));
+ printf("sizeof(struct Parser) = %d\n", sizeof(struct Parser));
+ printf("sizeof(struct CodeGen) = %d\n", sizeof(struct CodeGen));
+ return 0;
+}
+EOF