From 438faa73651bb4d700dd9d6eb589976402da10eb Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 4 May 2025 19:18:35 +0900 Subject: struct sizeof --- main.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--- tests/028.sh | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 tests/028.sh 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 -- cgit v1.2.3-70-g09d2