diff options
Diffstat (limited to 'compiler/codegen.cup')
| -rw-r--r-- | compiler/codegen.cup | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/compiler/codegen.cup b/compiler/codegen.cup index 41eea33..70a83c8 100644 --- a/compiler/codegen.cup +++ b/compiler/codegen.cup @@ -34,6 +34,16 @@ fn generate_syscall(num: int) { emit_asm(" syscall\n"); } +fn generate_lvalue_into_rax(node: Node*) { + if (node.typ == AST_LOCAL_VAR) { + let offset = node.d.variable.offset; + emit_asm(" mov rax, rbp\n"); + emit_asm(" sub rax, "); emit_num(offset); emit_asm("\n"); + } else { + die2("Unsupported type in generate_lvalue_into_rax: ", node_type_to_string(node.typ)); + } +} + fn generate_expr_into_rax(node: Node*) { if (node.typ == AST_LITERAL) { if (node.etyp.typ == TYPE_INT) { @@ -76,15 +86,42 @@ fn generate_expr_into_rax(node: Node*) { generate_expr_into_rax(node.d.binary.lhs); emit_asm(" pop rbx\n"); emit_asm(" imul rbx\n"); + } else if (is_lvalue(node.typ)) { + generate_lvalue_into_rax(node); + emit_asm(" mov rax, [rax]\n"); + + } else if (node.typ == AST_ASSIGN) { + putsln("..."); + generate_lvalue_into_rax(node.d.assign.lhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.assign.rhs); + emit_asm(" pop rbx\n"); + emit_asm(" mov [rbx], rax\n"); + + } else { + die2("Unsupported node type in generate_expr_into_rax: ", node_type_to_string(node.typ)); } } +fn generate_block(node: Node*); + fn generate_statement(node: Node*) { if (node.typ == AST_RETURN) { generate_expr_into_rax(node.d.unary); emit_asm(" mov rsp, rbp\n"); emit_asm(" pop rbp\n"); emit_asm(" ret\n"); + } else if (node.typ == AST_VARDECL) { + if (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 [rbp-"); emit_num(offset); emit_asm("], rax\n"); + } + } else if (node.typ == AST_BLOCK) { + generate_block(node); + } else { + // Default to a simple expression statement + generate_expr_into_rax(node); } } |