diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-05 19:23:38 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-05 19:23:38 -0500 |
| commit | cc13d887c77e0b09d7dc7d4aeb66841e06f52330 (patch) | |
| tree | 852eb220586a28bd71ee6361f792301608bc3829 | |
| parent | [compiler.cup] Add support for lexically scoped local variables (diff) | |
| download | cup-cc13d887c77e0b09d7dc7d4aeb66841e06f52330.tar.xz cup-cc13d887c77e0b09d7dc7d4aeb66841e06f52330.zip | |
[compiler.cup] Add codegen for relational + if/conditional support
| -rw-r--r-- | compiler/ast.cup | 13 | ||||
| -rw-r--r-- | compiler/codegen.cup | 85 |
2 files changed, 96 insertions, 2 deletions
diff --git a/compiler/ast.cup b/compiler/ast.cup index 689f7fb..82e8477 100644 --- a/compiler/ast.cup +++ b/compiler/ast.cup @@ -286,6 +286,13 @@ fn dump_ast(node: Node*, depth: int) { putsln(node_type_to_string(node.typ)); dump_ast(node.d.unary, depth + 1); + } else if (node.typ == AST_CONDITIONAL || node.typ == AST_IF) { + putsln(node_type_to_string(node.typ)); + dump_ast(node.d.conditional.cond, depth + 1); + dump_ast(node.d.conditional.then, depth + 1); + if (node.d.conditional.els) + dump_ast(node.d.conditional.els, depth + 1); + } else if (node.typ == AST_LITERAL) { if (node.etyp.typ == TYPE_INT) { putu(node.d.literal.as_int); putc('\n'); @@ -311,6 +318,12 @@ fn dump_ast(node: Node*, depth: int) { } else { putc('\n'); } + } else if (node.typ == AST_ASSIGN) { + putsln(node_type_to_string(node.typ)); + dump_ast(node.d.assign.lhs, depth + 1); + dump_ast(node.d.assign.rhs, depth + 1); + } else if (node.typ == AST_LOCAL_VAR || node.typ == AST_GLOBAL_VAR) { + putsln(node.d.variable.name); } else { putsln(node_type_to_string(node.typ)); } diff --git a/compiler/codegen.cup b/compiler/codegen.cup index 70a83c8..71ffb76 100644 --- a/compiler/codegen.cup +++ b/compiler/codegen.cup @@ -2,6 +2,7 @@ import "compiler/ast.cup" import "std/file.cup" let gen_out_file: File*; +let gen_label_counter = 0; fn emit_asm4(msg1: char*, msg2: char*, msg3: char*, msg4: char*) { fwrite(gen_out_file, msg1, strlen(msg1)); @@ -39,7 +40,7 @@ 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 { + } else { die2("Unsupported type in generate_lvalue_into_rax: ", node_type_to_string(node.typ)); } } @@ -51,18 +52,31 @@ fn generate_expr_into_rax(node: Node*) { } else { die("Unsupported literal type in generate_expr_into_rax"); } + } else if (node.typ == AST_CONDITIONAL) { + let label = ++gen_label_counter; + generate_expr_into_rax(node.d.conditional.cond); + emit_asm(" cmp rax, 0\n"); + emit_asm(" je .cond_els"); emit_num(label); emit_asm("\n"); + generate_expr_into_rax(node.d.conditional.then); + emit_asm(" jmp .cond"); emit_num(label); emit_asm("\n"); + emit_asm(".cond_els"); emit_num(label); emit_asm(":\n"); + generate_expr_into_rax(node.d.conditional.els); + emit_asm(".cond"); emit_num(label); emit_asm(":\n"); + } else if (node.typ == AST_PLUS) { generate_expr_into_rax(node.d.binary.rhs); emit_asm(" push rax\n"); generate_expr_into_rax(node.d.binary.lhs); emit_asm(" pop rbx\n"); emit_asm(" add rax, rbx\n"); + } else if (node.typ == AST_MINUS) { generate_expr_into_rax(node.d.binary.rhs); emit_asm(" push rax\n"); generate_expr_into_rax(node.d.binary.lhs); emit_asm(" pop rbx\n"); emit_asm(" sub rax, rbx\n"); + } else if (node.typ == AST_DIV) { generate_expr_into_rax(node.d.binary.rhs); emit_asm(" push rax\n"); @@ -86,6 +100,61 @@ 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 (node.typ == AST_EQ) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" sete al\n"); + emit_asm(" movzx rax, al\n"); + + } else if (node.typ == AST_NEQ) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" setne al\n"); + emit_asm(" movzx rax, al\n"); + + } else if (node.typ == AST_LT) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" setl al\n"); + emit_asm(" movzx rax, al\n"); + + } else if (node.typ == AST_LEQ) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" setle al\n"); + emit_asm(" movzx rax, al\n"); + + } else if (node.typ == AST_GT) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" setg al\n"); + emit_asm(" movzx rax, al\n"); + + } else if (node.typ == AST_GEQ) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rbx\n"); + emit_asm(" cmp rax, rbx\n"); + emit_asm(" setge al\n"); + emit_asm(" movzx rax, al\n"); + } else if (is_lvalue(node.typ)) { generate_lvalue_into_rax(node); emit_asm(" mov rax, [rax]\n"); @@ -110,7 +179,7 @@ fn generate_statement(node: Node*) { generate_expr_into_rax(node.d.unary); emit_asm(" mov rsp, rbp\n"); emit_asm(" pop rbp\n"); - emit_asm(" ret\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); @@ -119,6 +188,18 @@ fn generate_statement(node: Node*) { } } else if (node.typ == AST_BLOCK) { generate_block(node); + } else if (node.typ == AST_IF) { + let label = ++gen_label_counter; + generate_expr_into_rax(node.d.conditional.cond); + emit_asm(" cmp rax, 0\n"); + emit_asm(" je .els"); emit_num(label); emit_asm("\n"); + generate_block(node.d.conditional.then); + emit_asm(" jmp .if"); emit_num(label); emit_asm("\n"); + emit_asm(".els"); emit_num(label); emit_asm(":\n"); + if (node.d.conditional.els) + generate_block(node.d.conditional.els); + emit_asm(".if"); emit_num(label); emit_asm(":\n"); + } else { // Default to a simple expression statement generate_expr_into_rax(node); |