From 008d12251620366c3972c8884a33c63ddf4843ba Mon Sep 17 00:00:00 2001 From: pacien Date: Mon, 7 May 2018 14:44:11 +0200 Subject: Extract generator functions (partial commit pt2) --- src/generator.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 3 deletions(-) (limited to 'src/generator.c') diff --git a/src/generator.c b/src/generator.c index a7a7c72..004e559 100644 --- a/src/generator.c +++ b/src/generator.c @@ -7,7 +7,9 @@ #include #include "symbol_table.h" -void prologue() { +// ----- GLOBAL FUNCTIONS ----- + +void gen_prologue() { printf("extern printf\n"); printf("section .data\n"); printf("format_int db \"%%d\",10,0\n\n"); @@ -27,7 +29,7 @@ void prologue() { printf("push rbp\nmov rbp, rsp\n\n"); } -void const_declaration() { +void gen_const_declaration() { printf("mov rax,60 \n"); printf("mov rdi,0 \n"); printf("syscall \n"); @@ -37,7 +39,7 @@ void const_declaration() { loc_display_table(); } -void declaration(const char name[], int type, Scope scope) { +void gen_declaration(const char name[], int type, Scope scope) { switch (scope) { case GLOBAL: glo_addVar(name, type); @@ -50,4 +52,157 @@ void declaration(const char name[], int type, Scope scope) { printf("push 0\n"); } +// ----- READ AND PRINT FUNCTIONS ----- + +void gen_read(const char name[], Scope scope) { + switch (scope) { + case GLOBAL: + glo_lookup(name); + break; + case LOCAL: + loc_lookup(name); + break; + } +} + +void gen_print() { + printf("pop rax\n"); + printf("call print\n"); +} + +// ----- CONDITIONAL BRANCHING ------ + +void gen_if_label(int idx) { + printf(".end_if%d:\n", idx); + printf(";ENDIF\n\n"); +} + +void gen_if_start(int idx) { + printf("\n;BEGINIF\n"); + printf("pop rax\n"); + printf("cmp rax,0\n"); + printf("jz .end_if%d\n", idx); +} + +void gen_if_end(int idx) { + printf("jmp .end_ifelse%d\n", idx); + printf(".end_if%d:\n", idx); +} + +void gen_ifelse_end(int idx) { + printf(".end_ifelse%d:\n", idx); + printf("ENDIF\n\n"); +} + +// ----- OPERATORS ----- + +void gen_assign(int ident, Scope scope) { + // TODO: what's "$$" and how do we extract it? +} + +void gen_or(int left, int right, int idx) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + printf(";a OR c\n"); + printf("pop rax\n"); + printf("cmp rax,1\n"); + printf("je .true%d\n", idx); + printf("pop rcx\n"); + printf("cmp rcx,1\n"); + printf("jz .true%d\n", idx); + printf("push 0\n"); + printf("jmp .false%d\n", idx); + printf(".true%d:\n", idx); + printf("push 1\n"); + printf(".false%d:", idx); +} + +void gen_and(int left, int right, int idx) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + printf(";a AND c\n"); + printf("pop rax\n"); + printf("cmp rax,0\n"); + printf("jz .false%d\n", idx); + printf("pop rcx\n"); + printf("cmp rcx,0\n"); + printf("jz .false%d\n", idx); + printf("push 1\n"); + printf("jmp .true%d\n", idx); + printf(".false%d:\n", idx); + printf("push 0\n"); + printf(".true%d:", idx); +} + +void gen_eq(const char op[], int left, int right, int idx) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + printf(";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); + + if (!strcmp(op, "==")) + printf("je .true%d\n", idx); + else if (!strcmp(op, "!=")) + printf("jne .true%d\n", idx); + else + exit(1); // TODO: error on unexpected op + + printf("push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); +} + +void gen_order(const char op[], int left, int right, int idx) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + printf(";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); + + if (!strcmp(op, "<")) + printf("jl .true%d\n", idx); + else if (!strcmp(op, "<=")) + printf("jle .true%d\n", idx); + else if(!strcmp(op, ">")) + printf("jg .true%d\n", idx); + else if(!strcmp(op, "<=")) + printf("jge .true%d\n", idx); + else + exit(1); // TODO: error on unexpected op + + printf("push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); +} + +void gen_addsub(char op, int left, int right) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + switch (op) { + case '+': + printf(";E + T\npop rcx\npop rax\nadd rax,rcx\npush rax\n"); + break; + case '-': + printf(";E - T\npop rcx\npop rax\nsub rax,rcx\npush rax\n"); + break; + default: + exit(1); + } +} + +void gen_divstar(char op, int left, int right) { + check_expected_type(left, INT); + check_expected_type(right, INT); + + switch (op) { + case '*': + printf(";E * T\npop rax\npop rcx\nimul rax,rcx\npush rax\n"); + break; + case '/': + case '%': + printf(";E / T\npop rax\npop rcx\nxor rdx,rdx\nidiv rcx\n"); + printf("push %s\n", op == '/' ? "rax" : "rdx"); + break; + default: + exit(1); + } +} -- cgit v1.2.3