aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-05 19:23:38 -0500
committerMustafa Quraish <[email protected]>2022-02-05 19:23:38 -0500
commitcc13d887c77e0b09d7dc7d4aeb66841e06f52330 (patch)
tree852eb220586a28bd71ee6361f792301608bc3829
parent[compiler.cup] Add support for lexically scoped local variables (diff)
downloadcup-cc13d887c77e0b09d7dc7d4aeb66841e06f52330.tar.xz
cup-cc13d887c77e0b09d7dc7d4aeb66841e06f52330.zip
[compiler.cup] Add codegen for relational + if/conditional support
-rw-r--r--compiler/ast.cup13
-rw-r--r--compiler/codegen.cup85
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);