From 68d5048ecc9d2a7d29823f7acba30a1e60ef09b6 Mon Sep 17 00:00:00 2001 From: Mustafa Quraish Date: Sun, 6 Feb 2022 00:15:10 -0500 Subject: [cup] Add support for global (initialized) variables --- compiler/codegen.cup | 21 +++++++++++++++++++++ compiler/parser.cup | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'compiler') diff --git a/compiler/codegen.cup b/compiler/codegen.cup index 8c8ec95..68c3321 100644 --- a/compiler/codegen.cup +++ b/compiler/codegen.cup @@ -48,6 +48,10 @@ fn generate_lvalue_into_rax(node: Node*) { let offset = node.d.variable.offset; emit_asm(" mov rax, rbp\n"); emit_asm(" sub rax, "); emit_num(offset); emit_asm("\n"); + } else if (node.typ == AST_GLOBAL_VAR) { + let offset = node.d.variable.offset; + emit_asm(" mov rax, global_vars\n"); + emit_asm(" add rax, "); emit_num(offset); emit_asm("\n"); } else { die2("Unsupported type in generate_lvalue_into_rax: ", node_type_to_string(node.typ)); } @@ -351,6 +355,8 @@ fn generate_program(ast: Node*, file: File*) { let node: Node* = ast.d.block.children.data[i]; if (node.typ == AST_FUNC) { generate_function(node); + } else if (node.typ == AST_VARDECL) { + // Do nothing } else { die("Unknown node type in generate_program"); } @@ -379,9 +385,24 @@ fn generate_program(ast: Node*, file: File*) { emit_asm(" push rax\n"); } + // Initialize all the global variables + for (let i = 0; i < n; ++i) { + let node: Node* = ast.d.block.children.data[i]; + if (node.typ == AST_VARDECL && node.d.var_decl.init) { + generate_expr_into_rax(node.d.var_decl.init); + let offset = node.d.var_decl.var.offset; + emit_asm(" mov rbx, global_vars\n"); + emit_asm(" add rbx, "); emit_num(offset); emit_asm("\n"); + emit_asm(" mov [rbx], rax\n"); + } + } + emit_asm(" call func_main\n"); emit_asm(" mov rdi, rax\n"); generate_syscall(SYS_exit); generate_builtins(); + + emit_asm("section .bss\n"); + emit_asm(" global_vars: resb "); emit_num(p_global_offset); emit_asm("\n"); } \ No newline at end of file diff --git a/compiler/parser.cup b/compiler/parser.cup index 40df5a3..ffd8d8a 100644 --- a/compiler/parser.cup +++ b/compiler/parser.cup @@ -8,6 +8,9 @@ let p_current_function: Node* = null; let p_block_stack = vector_new(); let p_cur_stack_offset = 0; +let p_global_variables = vector_new(); +let p_global_offset = 0; + fn block_stack_push(block: Node*) { vector_push(p_block_stack, block); } @@ -41,6 +44,16 @@ fn find_local_variable(token: Token*): Variable* { return null; } +fn find_global_variable(token: Token*): Variable* { + for (let i = 0; i < p_global_variables.size; ++i) { + let var: Variable* = p_global_variables.data[i]; + if (streq(token.value.as_string, var.name)) { + return var; + } + } + return null; +} + fn find_function_definition(token: Token*): Node* { for (let i = 0; i < p_all_functions.size; ++i) { let func: Node* = p_all_functions.data[i]; @@ -53,6 +66,7 @@ fn find_function_definition(token: Token*): Node* { fn identifier_exists(token: Token*): int { if (find_local_variable(token)) return true; + if (find_global_variable(token)) return true; if (find_function_definition(token)) return true; if (find_builtin_function(token)) return true; return false; @@ -156,6 +170,14 @@ fn parse_identifier(lexer: Lexer*): Node* { return node; } + var = find_global_variable(&token); + if (var != null) { + node = node_new(AST_GLOBAL_VAR); + node.d.variable = var; + node.etyp = var.typ; + return node; + } + let func = find_function_definition(&token); if (func != null) { return parse_function_call_args(lexer, func); @@ -418,11 +440,21 @@ fn add_variable_to_current_block(var: Variable*) { p_current_function.d.func.max_locals_size = max_offset; } +fn add_global_variable(var: Variable*) { + var.offset = p_global_offset; + let var_size = align_up(size_for_type(var.typ), 8); + p_global_offset = p_global_offset + var_size; + vector_push(p_global_variables, var); +} + fn parse_var_declaration(lexer: Lexer*): Node* { let token: Token; lexer_next_assert(lexer, &token, TOKEN_LET); lexer_next_assert(lexer, &token, TOKEN_IDENTIFIER); + + let is_global = (p_current_function == null); + // TODO: check if identifier is already defined let node = node_new(AST_VARDECL); let decl = &node.d.var_decl; @@ -442,7 +474,11 @@ fn parse_var_declaration(lexer: Lexer*): Node* { die_loc(&token.loc, "Expected ':' or '=' after variable declaration"); } - add_variable_to_current_block(&decl.var); + if (is_global) { + add_global_variable(&decl.var); + } else { + add_variable_to_current_block(&decl.var); + } return node; } -- cgit v1.2.3