aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-06 00:15:10 -0500
committerMustafa Quraish <[email protected]>2022-02-06 00:15:10 -0500
commit68d5048ecc9d2a7d29823f7acba30a1e60ef09b6 (patch)
tree90db2d77837bdad86665dda449415b54d80967c6
parent[cup] Add support for builtin functions, add `print()` (diff)
downloadcup-68d5048ecc9d2a7d29823f7acba30a1e60ef09b6.tar.xz
cup-68d5048ecc9d2a7d29823f7acba30a1e60ef09b6.zip
[cup] Add support for global (initialized) variables
-rw-r--r--compiler/codegen.cup21
-rw-r--r--compiler/parser.cup38
2 files changed, 58 insertions, 1 deletions
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;
}