diff options
| -rw-r--r-- | codegen.c | 14 | ||||
| -rw-r--r-- | parse.c | 76 | ||||
| -rw-r--r-- | preprocess.c | 10 | ||||
| -rw-r--r-- | tests/088.sh | 35 |
4 files changed, 109 insertions, 26 deletions
@@ -275,11 +275,10 @@ void codegen_assign_expr(CodeGen* g, AstNode* ast) { void codegen_func_call(CodeGen* g, AstNode* ast) { String* func_name = &ast->name; - int i; if (string_equals_cstr(func_name, "va_start")) { printf(" # va_start BEGIN\n"); - for (i = 0; i < 6; ++i) { + for (int i = 0; i < 6; ++i) { printf(" mov rax, %s\n", param_reg(i)); printf(" mov [rbp-%d], rax\n", 8 + (LVAR_MAX - 4 - i) * 8); } @@ -300,11 +299,11 @@ void codegen_func_call(CodeGen* g, AstNode* ast) { } AstNode* args = ast->node_args; - for (i = 0; i < args->node_len; ++i) { + for (int i = 0; i < args->node_len; ++i) { AstNode* arg = args->node_items + i; codegen_expr(g, arg, GenMode_rval); } - for (i = args->node_len - 1; i >= 0; --i) { + for (int i = args->node_len - 1; i >= 0; --i) { printf(" pop %s\n", param_reg(i)); } @@ -529,18 +528,17 @@ void codegen_func(CodeGen* g, AstNode* ast) { void codegen(Program* prog) { CodeGen* g = codegen_new(); - int i; printf(".intel_syntax noprefix\n\n"); printf(".section .rodata\n\n"); - for (i = 0; prog->str_literals[i]; ++i) { + for (int i = 0; prog->str_literals[i]; ++i) { printf(".Lstr__%d:\n", i + 1); printf(" .string \"%s\"\n\n", prog->str_literals[i]); } printf(".bss\n\n"); - for (i = 0; i < prog->vars->node_len; ++i) { + for (int i = 0; i < prog->vars->node_len; ++i) { AstNode* var = prog->vars->node_items + i; printf(" .lcomm %.*s, %d\n", var->name.len, var->name.data, type_sizeof(var->ty)); } @@ -548,7 +546,7 @@ void codegen(Program* prog) { printf(".globl main\n\n"); printf(".text\n\n"); - for (i = 0; i < prog->funcs->node_len; ++i) { + for (int i = 0; i < prog->funcs->node_len; ++i) { AstNode* func = prog->funcs->node_items + i; codegen_func(g, func); } @@ -7,6 +7,13 @@ struct LocalVar { }; typedef struct LocalVar LocalVar; +struct Scope { + struct Scope* outer; + String* lvar_names; + int* lvar_indices; +}; +typedef struct Scope Scope; + struct GlobalVar { String name; Type* ty; @@ -24,6 +31,7 @@ struct Parser { int pos; LocalVar* lvars; int n_lvars; + Scope* scope; GlobalVar* gvars; int n_gvars; Func* funcs; @@ -83,15 +91,30 @@ Token* expect(Parser* p, TokenKind expected) { token_stringify(t)); } -int find_lvar(Parser* p, const String* name) { - for (int i = 0; i < p->n_lvars; ++i) { - if (string_equals(&p->lvars[i].name, name)) { - return i; +int find_lvar_in_scope(Parser* p, Scope* scope, const String* name) { + for (int i = 0; i < LVAR_MAX; ++i) { + if (string_equals(&scope->lvar_names[i], name)) { + return scope->lvar_indices[i]; } } return -1; } +int find_lvar_in_current_scope(Parser* p, const String* name) { + return find_lvar_in_scope(p, p->scope, name); +} + +int find_lvar(Parser* p, const String* name) { + Scope* scope = p->scope; + while (scope) { + int idx = find_lvar_in_scope(p, scope, name); + if (idx != -1) + return idx; + scope = scope->outer; + } + return -1; +} + int calc_stack_offset(Parser* p, Type* ty, BOOL is_param) { int align; if (is_param) { @@ -119,6 +142,13 @@ int add_lvar(Parser* p, String* name, Type* ty, BOOL is_param) { p->lvars[p->n_lvars].name = *name; p->lvars[p->n_lvars].ty = ty; p->lvars[p->n_lvars].stack_offset = stack_offset; + for (int i = 0; i < LVAR_MAX; ++i) { + if (p->scope->lvar_names[i].len == 0) { + p->scope->lvar_names[i] = *name; + p->scope->lvar_indices[i] = p->n_lvars; + break; + } + } ++p->n_lvars; return stack_offset; } @@ -209,6 +239,28 @@ int find_typedef(Parser* p, const String* name) { return -1; } +void enter_scope(Parser* p) { + Scope* outer_scope = p->scope; + p->scope = calloc(1, sizeof(Scope)); + p->scope->outer = outer_scope; + p->scope->lvar_names = calloc(LVAR_MAX, sizeof(String)); + p->scope->lvar_indices = calloc(LVAR_MAX, sizeof(int)); +} + +void leave_scope(Parser* p) { + p->scope = p->scope->outer; +} + +void enter_func(Parser* p) { + p->lvars = calloc(LVAR_MAX, sizeof(LocalVar)); + p->n_lvars = 0; + enter_scope(p); +} + +void leave_func(Parser* p) { + leave_scope(p); +} + AstNode* parse_expr(Parser* p); AstNode* parse_stmt(Parser* p); @@ -734,10 +786,10 @@ AstNode* parse_var_decl(Parser* p) { } expect(p, TokenKind_semicolon); - if (find_lvar(p, name) != -1 || find_gvar(p, name) != -1) { + if (find_lvar_in_current_scope(p, name) != -1) { // TODO: use name's location. - fatal_error("%s:%d: parse_var_decl: %.*s redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, - name->len, name->data); + fatal_error("%s:%d: '%.*s' redeclared", peek_token(p)->loc.filename, peek_token(p)->loc.line, name->len, + name->data); } int stack_offset = add_lvar(p, name, ty, FALSE); @@ -762,6 +814,7 @@ AstNode* parse_for_stmt(Parser* p) { AstNode* init = NULL; AstNode* cond = NULL; AstNode* update = NULL; + enter_scope(p); if (peek_token(p)->kind != TokenKind_semicolon) { if (is_type_token(p, peek_token(p))) { init = parse_var_decl(p)->node_expr; @@ -783,6 +836,7 @@ AstNode* parse_for_stmt(Parser* p) { } expect(p, TokenKind_paren_r); AstNode* body = parse_stmt(p); + leave_scope(p); AstNode* stmt = ast_new(AstNodeKind_for_stmt); stmt->node_cond = cond; @@ -843,10 +897,12 @@ AstNode* parse_expr_stmt(Parser* p) { AstNode* parse_block_stmt(Parser* p) { AstNode* list = ast_new_list(4); expect(p, TokenKind_brace_l); + enter_scope(p); while (peek_token(p)->kind != TokenKind_brace_r) { AstNode* stmt = parse_stmt(p); ast_append(list, stmt); } + leave_scope(p); expect(p, TokenKind_brace_r); return list; } @@ -883,11 +939,6 @@ AstNode* parse_stmt(Parser* p) { } } -void enter_func(Parser* p) { - p->lvars = calloc(LVAR_MAX, sizeof(LocalVar)); - p->n_lvars = 0; -} - void register_params(Parser* p, AstNode* params) { for (int i = 0; i < params->node_len; ++i) { AstNode* param = params->node_items + i; @@ -996,6 +1047,7 @@ AstNode* parse_func_decl_or_def(Parser* p) { enter_func(p); register_params(p, params); AstNode* body = parse_block_stmt(p); + leave_func(p); AstNode* func = ast_new(AstNodeKind_func_def); func->ty = ty; func->name = *name; diff --git a/preprocess.c b/preprocess.c index b097bfb..f11bde2 100644 --- a/preprocess.c +++ b/preprocess.c @@ -922,7 +922,6 @@ Token* process_include_directive(Preprocessor* pp, Token* tok, Token* tok2) { Token* process_define_directive(Preprocessor* pp, Token* tok, Token* tok2) { Token* tok3 = NULL; PpMacro* pp_macro; - int i; ++tok2; tok2 = skip_whitespace(tok2); if (tok2->kind != TokenKind_ident) { @@ -948,7 +947,7 @@ Token* process_define_directive(Preprocessor* pp, Token* tok, Token* tok2) { pp_macro->name = macro_name->raw; pp_macro->n_replacements = tok3 - tok2; pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); - for (i = 0; i < pp_macro->n_replacements; ++i) { + for (int i = 0; i < pp_macro->n_replacements; ++i) { pp_macro->replacements[i] = tok2[i]; } } else { @@ -961,7 +960,7 @@ Token* process_define_directive(Preprocessor* pp, Token* tok, Token* tok2) { pp_macro->name = macro_name->raw; pp_macro->n_replacements = tok3 - tok2; pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); - for (i = 0; i < pp_macro->n_replacements; ++i) { + for (int i = 0; i < pp_macro->n_replacements; ++i) { pp_macro->replacements[i] = tok2[i]; } } @@ -1001,20 +1000,19 @@ BOOL expand_macro(Preprocessor* pp, Token* tok) { return FALSE; } - int i; SourceLocation original_loc = tok->loc; PpMacro* pp_macro = pp->pp_macros->data + pp_macro_idx; if (pp_macro->kind == PpMacroKind_func) { // also consume '(' and ')' replace_pp_tokens(pp, tok, tok + 3, pp_macro->n_replacements, pp_macro->replacements); // Inherit a source location from the original macro token. - for (i = 0; i < pp_macro->n_replacements; ++i) { + for (int i = 0; i < pp_macro->n_replacements; ++i) { tok[i].loc = original_loc; } } else if (pp_macro->kind == PpMacroKind_obj) { replace_pp_tokens(pp, tok, tok + 1, pp_macro->n_replacements, pp_macro->replacements); // Inherit a source location from the original macro token. - for (i = 0; i < pp_macro->n_replacements; ++i) { + for (int i = 0; i < pp_macro->n_replacements; ++i) { tok[i].loc = original_loc; } } else if (pp_macro->kind == PpMacroKind_builtin_file) { diff --git a/tests/088.sh b/tests/088.sh new file mode 100644 index 0000000..6630cf0 --- /dev/null +++ b/tests/088.sh @@ -0,0 +1,35 @@ +set -e + +cat <<'EOF' > expected +0 +1 +2 +3 +4 +0 +1 +2 +3 +4 +43 +42 +EOF + +bash ../../test_diff.sh <<'EOF' +int printf(); + +int main() { + for (int i = 0; i < 5; i++) { + printf("%d\n", i); + } + for (int i = 0; i < 5; i++) { + printf("%d\n", i); + } + int x = 42; + { + int x = 43; + printf("%d\n", x); + } + printf("%d\n", x); +} +EOF |
