diff --git a/ccc.h b/ccc.h index 7b58b4d..2c491d6 100644 --- a/ccc.h +++ b/ccc.h @@ -54,6 +54,7 @@ typedef struct Var Var; struct Var { char *name; // Variable name Type *ty; // Type + Token *tok; // for error message bool is_local; // local or global // local variable int offset; // Offset from RBP @@ -173,13 +174,14 @@ typedef enum { } TypeKind; struct Type { TypeKind kind; - bool is_typedef; // typedef - bool is_static; // static - int align; // alignment - Type *base; // pointer or array - int array_size; // array - Member *members; // struct - Type *return_ty; // function + bool is_typedef; // typedef + bool is_static; // static + bool is_incomplete; // incomplete array + int align; // alignment + Type *base; // pointer or array + int array_size; // array + Member *members; // struct + Type *return_ty; // function }; // Struct member @@ -200,7 +202,7 @@ Type *enum_type(); Type *func_type(Type *return_ty); Type *pointer_to(Type *base); Type *array_of(Type *base, int size); -int size_of(Type *ty); +int size_of(Type *ty, Token *tok); void add_type(Program *prog); // diff --git a/codegen.c b/codegen.c index a8b7ccd..1977929 100644 --- a/codegen.c +++ b/codegen.c @@ -16,7 +16,7 @@ void truncate(Type *ty) { printf(" setne al\n"); } - int sz = size_of(ty); + int sz = size_of(ty, NULL); if (sz == 1) { printf(" movsx rax, al\n"); } else if (sz == 2) { @@ -64,7 +64,7 @@ void gen_lval(Node *node) { void load(Type *ty) { printf(" pop rax\n"); - int sz = size_of(ty); + int sz = size_of(ty, NULL); if (sz == 1) { printf(" movsx rax, byte ptr [rax]\n"); } else if (sz == 2) { @@ -88,7 +88,7 @@ void store(Type *ty) { printf(" movzb rdi, dil\n"); } - int sz = size_of(ty); + int sz = size_of(ty, NULL); if (sz == 1) { printf(" mov [rax], dil\n"); } else if (sz == 2) { @@ -102,15 +102,17 @@ void store(Type *ty) { printf(" push rdi\n"); } -void inc(Type *ty) { +void inc(Node *node) { + int sz = node->ty->base ? size_of(node->ty->base, node->tok) : 1; printf(" pop rax\n"); - printf(" add rax, %d\n", ty->base ? size_of(ty->base) : 1); + printf(" add rax, %d\n", sz); printf(" push rax\n"); } -void dec(Type *ty) { +void dec(Node *node) { + int sz = node->ty->base ? size_of(node->ty->base, node->tok) : 1; printf(" pop rax\n"); - printf(" sub rax, %d\n", ty->base ? size_of(ty->base) : 1); + printf(" sub rax, %d\n", sz); printf(" push rax\n"); } @@ -287,21 +289,21 @@ void gen(Node *node) { gen_lval(node->lhs); printf(" push [rsp]\n"); load(node->ty); - inc(node->ty); + inc(node); store(node->ty); return; case ND_PRE_DEC: gen_lval(node->lhs); printf(" push [rsp]\n"); load(node->ty); - dec(node->ty); + dec(node); store(node->ty); return; case ND_POST_INC: gen_lval(node->lhs); printf(" push [rsp]\n"); load(node->ty); - inc(node->ty); + inc(node); store(node->ty); dec(node->ty); return; @@ -309,7 +311,7 @@ void gen(Node *node) { gen_lval(node->lhs); printf(" push [rsp]\n"); load(node->ty); - dec(node->ty); + dec(node); store(node->ty); inc(node->ty); return; @@ -327,13 +329,13 @@ void gen(Node *node) { switch (node->kind) { case ND_A_ADD: if (node->ty->base) { - printf(" imul rdi, %d\n", size_of(node->ty->base)); + printf(" imul rdi, %d\n", size_of(node->ty->base, node->tok)); } printf(" add rax, rdi\n"); break; case ND_A_SUB: if (node->ty->base) { - printf(" imul rdi, %d\n", size_of(node->ty->base)); + printf(" imul rdi, %d\n", size_of(node->ty->base, node->tok)); } printf(" sub rax, rdi\n"); break; @@ -376,13 +378,13 @@ void gen(Node *node) { switch (node->kind) { case ND_ADD: if (node->ty->base) { - printf(" imul rdi, %d\n", size_of(node->ty->base)); + printf(" imul rdi, %d\n", size_of(node->ty->base, node->tok)); } printf(" add rax, rdi\n"); break; case ND_SUB: if (node->ty->base) { - printf(" imul rdi, %d\n", size_of(node->ty->base)); + printf(" imul rdi, %d\n", size_of(node->ty->base, node->tok)); } printf(" sub rax, rdi\n"); break; @@ -427,7 +429,7 @@ void gen(Node *node) { } void load_arg(Var *var, int idx) { - int sz = size_of(var->ty); + int sz = size_of(var->ty, var->tok); if (sz == 1) { printf(" mov [rbp-%d], %s\n", var->offset, argreg1[idx]); } else if (sz == 2) { @@ -446,7 +448,7 @@ void emit_data(Program *prog) { Var *var = vl->var; printf("%s:\n", var->name); if (!var->contents) { - printf(" .zero %d\n", size_of(var->ty)); + printf(" .zero %d\n", size_of(var->ty, var->tok)); continue; } for (int i = 0; i < var->cont_len; i++) { diff --git a/main.c b/main.c index cd42a78..d613862 100644 --- a/main.c +++ b/main.c @@ -37,7 +37,7 @@ int main(int argc, char **argv) { for (VarList *vl = fn->locals; vl; vl = vl->next) { Var *var = vl->var; offset = align_to(offset, var->ty->align); - offset += size_of(var->ty); + offset += size_of(var->ty, var->tok); var->offset = offset; } fn->stack_size = align_to(offset, 8); diff --git a/parse.c b/parse.c index e1888df..a476306 100644 --- a/parse.c +++ b/parse.c @@ -19,12 +19,29 @@ struct TagScope { Type *ty; }; +typedef struct { + VarScope *var_scope; + TagScope *tag_scope; +} Scope; + VarList *locals; VarList *globals; VarScope *var_scope; TagScope *tag_scope; +Scope *enter_scope() { + Scope *sc = calloc(1, sizeof(Scope)); + sc->var_scope = var_scope; + sc->tag_scope = tag_scope; + return sc; +} + +void leave_scope(Scope *sc) { + var_scope = sc->var_scope; + tag_scope = sc->tag_scope; +} + // Find a variable or a typedef by name. VarScope *find_var(Token *tok) { for (VarScope *sc = var_scope; sc; sc = sc->next) { @@ -85,11 +102,13 @@ VarScope *push_scope(char *name) { return sc; } -Var *push_var(char *name, Type *ty, bool is_local) { +Var *push_var(char *name, Type *ty, bool is_local, Token* tok) { Var *var = calloc(1, sizeof(Var)); var->name = name; var->ty = ty; var->is_local = is_local; + var->tok = tok; + VarList *vl = calloc(1, sizeof(VarList)); vl->var = var; if (is_local) { @@ -324,13 +343,14 @@ Type *abstract_declarator(Type *ty) { return type_suffix(ty); } -// type-suffix = ("[" num "]" type-suffix)? +// type-suffix = ("[" num? "]" type-suffix)? Type *type_suffix(Type *ty) { if (!consume("[")) { return ty; } - int sz = expect_number(); - expect("]"); + + int sz = 0; + bool is_incomplete = true; ty = type_suffix(ty); return array_of(ty, sz); }