public inbox for ~johnnyrichard/olang-devel@lists.sr.ht
 help / color / mirror / code / Atom feed
From: Johnny Richard <johnny@johnnyrichard.com>
To: ~johnnyrichard/olang-devel@lists.sr.ht
Cc: Johnny Richard <johnny@johnnyrichard.com>
Subject: [PATCH olang v1 3/3] codegen: add support scopes and symbols lookups for var
Date: Sat, 21 Sep 2024 02:20:40 +0200	[thread overview]
Message-ID: <20240921002250.902558-4-johnny@johnnyrichard.com> (raw)
In-Reply-To: <20240921002250.902558-1-johnny@johnnyrichard.com>

It introduces a new struct designed to maintain the stack offset for
local variables. This data structure facilitates the sharing of state
between function calls, including essential information such as the FILE
*out pointer.

Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
---
 src/codegen_linux_x86_64.c                    | 347 ++++++++++--------
 src/codegen_linux_x86_64.h                    |  16 +-
 src/main.c                                    |   8 +-
 .../integration/tests/0024_var_definition.ol  |   4 +
 4 files changed, 229 insertions(+), 146 deletions(-)

diff --git a/src/codegen_linux_x86_64.c b/src/codegen_linux_x86_64.c
index 8ed127c..4e0ea52 100644
--- a/src/codegen_linux_x86_64.c
+++ b/src/codegen_linux_x86_64.c
@@ -20,22 +20,38 @@
 
 #include "codegen_linux_x86_64.h"
 #include "list.h"
+#include "map.h"
+#include "scope.h"
 
 #define SYS_exit (60)
+#define PTR_HEX_CSTR_SIZE (18 + 1)
 
+// FIXME: move label_index to codegen_linux_x86_64_t structure
 size_t label_index;
 
 static void
-codegen_linux_x86_64_emit_start_entrypoint(FILE *out);
+codegen_linux_x86_64_emit_start_entrypoint(codegen_x86_64_t *codegen);
 
 static void
-codegen_linux_x86_64_emit_function(FILE *out, ast_fn_definition_t *fn);
+codegen_linux_x86_64_emit_function(codegen_x86_64_t *codegen, ast_fn_definition_t *fn);
 
 void
-codegen_linux_x86_64_emit_program(FILE *out, ast_node_t *node)
+codegen_linux_x86_64_init(codegen_x86_64_t *codegen, arena_t *arena, FILE *out)
+{
+    assert(codegen);
+    assert(arena);
+    assert(codegen);
+    codegen->base_offset = 0;
+    codegen->symbols_stack_offset = map_new(arena);
+    codegen->out = out;
+    codegen->arena = arena;
+}
+
+void
+codegen_linux_x86_64_emit_program(codegen_x86_64_t *codegen, ast_node_t *node)
 {
     label_index = 0;
-    codegen_linux_x86_64_emit_start_entrypoint(out);
+    codegen_linux_x86_64_emit_start_entrypoint(codegen);
 
     assert(node->kind == AST_NODE_PROGRAM);
     ast_program_t program = node->as_program;
@@ -43,20 +59,20 @@ codegen_linux_x86_64_emit_program(FILE *out, ast_node_t *node)
     ast_fn_definition_t fn = program.fn->as_fn_def;
 
     assert(string_view_eq_to_cstr(fn.identifier, "main"));
-    codegen_linux_x86_64_emit_function(out, &fn);
+    codegen_linux_x86_64_emit_function(codegen, &fn);
 }
 
 static void
-codegen_linux_x86_64_emit_start_entrypoint(FILE *out)
+codegen_linux_x86_64_emit_start_entrypoint(codegen_x86_64_t *codegen)
 {
-    fprintf(out, ".text\n");
-    fprintf(out, ".globl _start\n\n");
-
-    fprintf(out, "_start:\n");
-    fprintf(out, "    call main\n");
-    fprintf(out, "    mov %%eax, %%edi\n");
-    fprintf(out, "    mov $%d, %%eax\n", SYS_exit);
-    fprintf(out, "    syscall\n");
+    fprintf(codegen->out, ".text\n");
+    fprintf(codegen->out, ".globl _start\n\n");
+
+    fprintf(codegen->out, "_start:\n");
+    fprintf(codegen->out, "    call main\n");
+    fprintf(codegen->out, "    mov %%eax, %%edi\n");
+    fprintf(codegen->out, "    mov $%d, %%eax\n", SYS_exit);
+    fprintf(codegen->out, "    syscall\n");
 }
 
 static size_t
@@ -66,7 +82,7 @@ codegen_linux_x86_64_get_next_label(void)
 }
 
 static void
-codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node)
+codegen_linux_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
 {
     switch (expr_node->kind) {
         case AST_NODE_LITERAL: {
@@ -74,200 +90,215 @@ codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node)
             assert(literal_u32.kind == AST_LITERAL_U32);
             uint32_t n = literal_u32.as_u32;
 
-            fprintf(out, "    mov $%d, %%rax\n", n);
+            fprintf(codegen->out, "    mov $%d, %%rax\n", n);
+            return;
+        }
+        case AST_NODE_REF: {
+            ast_ref_t ref = expr_node->as_ref;
+
+            symbol_t *symbol = scope_lookup(ref.scope, ref.identifier);
+            assert(symbol);
+
+            char symbol_ptr[PTR_HEX_CSTR_SIZE];
+            sprintf(symbol_ptr, "%p", (void *)symbol);
+
+            size_t *offset = (size_t *)map_get(codegen->symbols_stack_offset, symbol_ptr);
+            assert(offset);
+
+            fprintf(codegen->out, "    mov -%ld(%%rbp), %%rax\n", *offset);
             return;
         }
         case AST_NODE_BINARY_OP: {
             ast_binary_op_t bin_op = expr_node->as_bin_op;
             switch (bin_op.kind) {
                 case AST_BINOP_ADDITION: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    add %%rcx, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    add %%rcx, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_MULTIPLICATION: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    mul %%rcx\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    mul %%rcx\n");
 
                     return;
                 }
                 case AST_BINOP_DIVISION: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    xor %%rdx, %%rdx\n");
-                    fprintf(out, "    div %%rcx\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    xor %%rdx, %%rdx\n");
+                    fprintf(codegen->out, "    div %%rcx\n");
 
                     return;
                 }
                 case AST_BINOP_REMINDER: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
-                    fprintf(out, "    xor %%edx, %%edx\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
+                    fprintf(codegen->out, "    xor %%edx, %%edx\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    xor %%rdx, %%rdx\n");
-                    fprintf(out, "    div %%rcx\n");
-                    fprintf(out, "    mov %%edx, %%eax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    xor %%rdx, %%rdx\n");
+                    fprintf(codegen->out, "    div %%rcx\n");
+                    fprintf(codegen->out, "    mov %%edx, %%eax\n");
 
                     return;
                 }
                 case AST_BINOP_SUBTRACTION: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    sub %%rcx, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    sub %%rcx, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_EQ: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    sete %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    sete %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_LT: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    setl %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    setl %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_GT: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    setg %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    setg %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_NEQ: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    setne %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    setne %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_LEQ: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    setle %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    setle %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_CMP_GEQ: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    cmp %%rcx, %%rax\n");
-                    fprintf(out, "    setge %%al\n");
-                    fprintf(out, "    movzb %%al, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    cmp %%rcx, %%rax\n");
+                    fprintf(codegen->out, "    setge %%al\n");
+                    fprintf(codegen->out, "    movzb %%al, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_BITWISE_LSHIFT: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    shl %%cl, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    shl %%cl, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_BITWISE_RSHIFT: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    shr %%cl, %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    shr %%cl, %%rax\n");
 
                     return;
                 }
                 case AST_BINOP_BITWISE_XOR: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    xor %%ecx, %%eax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    xor %%ecx, %%eax\n");
 
                     return;
                 }
                 case AST_BINOP_BITWISE_AND: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    and %%ecx, %%eax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    and %%ecx, %%eax\n");
 
                     return;
                 }
                 case AST_BINOP_BITWISE_OR: {
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    push %%rax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    push %%rax\n");
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    pop %%rcx\n");
-                    fprintf(out, "    or %%ecx, %%eax\n");
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    pop %%rcx\n");
+                    fprintf(codegen->out, "    or %%ecx, %%eax\n");
 
                     return;
                 }
                 case AST_BINOP_LOGICAL_AND: {
                     size_t label_exit = codegen_linux_x86_64_get_next_label();
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    cmp $0, %%rax\n");
-                    fprintf(out, "    je .L%ld\n", label_exit);
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    cmp $0, %%rax\n");
+                    fprintf(codegen->out, "    je .L%ld\n", label_exit);
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    cmp $0, %%rax\n");
-                    fprintf(out, "    je .L%ld\n", label_exit);
-                    fprintf(out, "    mov $1, %%rax\n");
-                    fprintf(out, ".L%ld:\n", label_exit);
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    cmp $0, %%rax\n");
+                    fprintf(codegen->out, "    je .L%ld\n", label_exit);
+                    fprintf(codegen->out, "    mov $1, %%rax\n");
+                    fprintf(codegen->out, ".L%ld:\n", label_exit);
 
                     return;
                 }
@@ -275,17 +306,17 @@ codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node)
                     size_t label_t = codegen_linux_x86_64_get_next_label();
                     size_t label_f = codegen_linux_x86_64_get_next_label();
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.lhs);
-                    fprintf(out, "    cmp $0, %%rax\n");
-                    fprintf(out, "    jne .L%ld\n", label_t);
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.lhs);
+                    fprintf(codegen->out, "    cmp $0, %%rax\n");
+                    fprintf(codegen->out, "    jne .L%ld\n", label_t);
 
-                    codegen_linux_x86_64_emit_expression(out, bin_op.rhs);
-                    fprintf(out, "    cmp $0, %%rax\n");
-                    fprintf(out, "    je .L%ld\n", label_f);
+                    codegen_linux_x86_64_emit_expression(codegen, bin_op.rhs);
+                    fprintf(codegen->out, "    cmp $0, %%rax\n");
+                    fprintf(codegen->out, "    je .L%ld\n", label_f);
 
-                    fprintf(out, ".L%ld:\n", label_t);
-                    fprintf(out, "    mov $1, %%rax\n");
-                    fprintf(out, ".L%ld:\n", label_f);
+                    fprintf(codegen->out, ".L%ld:\n", label_t);
+                    fprintf(codegen->out, "    mov $1, %%rax\n");
+                    fprintf(codegen->out, ".L%ld:\n", label_f);
 
                     return;
                 }
@@ -300,7 +331,7 @@ codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node)
     }
 }
 static void
-codegen_linux_x86_64_emit_block(FILE *out, ast_block_t *block)
+codegen_linux_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
 {
 
     size_t nodes_len = list_size(block->nodes);
@@ -313,12 +344,37 @@ codegen_linux_x86_64_emit_block(FILE *out, ast_block_t *block)
 
                 ast_node_t *expr = return_stmt.data;
 
-                codegen_linux_x86_64_emit_expression(out, expr);
+                codegen_linux_x86_64_emit_expression(codegen, expr);
+
+                fprintf(codegen->out, "    ret\n");
 
-                fprintf(out, "    ret\n");
+                break;
+            }
+
+            case AST_NODE_VAR_DEF: {
+                ast_var_definition_t var_def = node->as_var_def;
+                scope_t *scope = var_def.scope;
+
+                symbol_t *symbol = scope_lookup(scope, var_def.identifier);
+                assert(symbol);
+
+                char symbol_ptr[PTR_HEX_CSTR_SIZE];
+                sprintf(symbol_ptr, "%p", (void *)symbol);
+
+                if (var_def.value) {
+                    codegen_linux_x86_64_emit_expression(codegen, var_def.value);
+                }
+
+                codegen->base_offset += 8;
+                size_t *offset = arena_alloc(codegen->arena, sizeof(size_t));
+                *offset = codegen->base_offset;
+
+                map_put(codegen->symbols_stack_offset, symbol_ptr, offset);
+                fprintf(codegen->out, "    mov %%rax, -%ld(%%rbp)\n", codegen->base_offset);
 
                 break;
             }
+
             case AST_NODE_IF_STMT: {
                 ast_if_stmt_t if_stmt = node->as_if_stmt;
 
@@ -329,28 +385,30 @@ codegen_linux_x86_64_emit_block(FILE *out, ast_block_t *block)
                 size_t end_if_label = codegen_linux_x86_64_get_next_label();
                 size_t end_else_label = codegen_linux_x86_64_get_next_label();
 
-                codegen_linux_x86_64_emit_expression(out, cond);
-                fprintf(out, "    cmp $1, %%rax\n");
-                fprintf(out, "    jnz .L%ld\n", end_if_label);
+                codegen_linux_x86_64_emit_expression(codegen, cond);
+                fprintf(codegen->out, "    cmp $1, %%rax\n");
+                fprintf(codegen->out, "    jnz .L%ld\n", end_if_label);
 
                 assert(then->kind == AST_NODE_BLOCK && "invalid if-then block");
                 ast_block_t then_block = then->as_block;
 
-                codegen_linux_x86_64_emit_block(out, &then_block);
-                fprintf(out, "    jmp .L%ld\n", end_else_label);
+                codegen_linux_x86_64_emit_block(codegen, &then_block);
+                fprintf(codegen->out, "    jmp .L%ld\n", end_else_label);
 
-                fprintf(out, ".L%ld:\n", end_if_label);
+                fprintf(codegen->out, ".L%ld:\n", end_if_label);
 
                 if (_else != NULL) {
                     ast_block_t else_block = _else->as_block;
-                    codegen_linux_x86_64_emit_block(out, &else_block);
+                    codegen_linux_x86_64_emit_block(codegen, &else_block);
                 }
 
-                fprintf(out, ".L%ld:\n", end_else_label);
+                fprintf(codegen->out, ".L%ld:\n", end_else_label);
 
                 break;
             }
             default: {
+                // FIXME: improve error: replace the node->kind to a string representation
+                fprintf(stderr, "node kind %d not supported\n", node->kind);
                 assert(0 && "unsupported block statement");
                 break;
             }
@@ -359,13 +417,16 @@ codegen_linux_x86_64_emit_block(FILE *out, ast_block_t *block)
 }
 
 static void
-codegen_linux_x86_64_emit_function(FILE *out, ast_fn_definition_t *fn)
+codegen_linux_x86_64_emit_function(codegen_x86_64_t *codegen, ast_fn_definition_t *fn)
 {
+    codegen->base_offset = 0;
     ast_node_t *block_node = fn->block;
-    fprintf(out, "" SV_FMT ":\n", SV_ARG(fn->identifier));
+    fprintf(codegen->out, "" SV_FMT ":\n", SV_ARG(fn->identifier));
+
+    fprintf(codegen->out, "    mov %%rsp, %%rbp\n");
 
     assert(block_node->kind == AST_NODE_BLOCK);
     ast_block_t block = block_node->as_block;
 
-    codegen_linux_x86_64_emit_block(out, &block);
+    codegen_linux_x86_64_emit_block(codegen, &block);
 }
diff --git a/src/codegen_linux_x86_64.h b/src/codegen_linux_x86_64.h
index 2050c91..cad530a 100644
--- a/src/codegen_linux_x86_64.h
+++ b/src/codegen_linux_x86_64.h
@@ -17,9 +17,23 @@
 #ifndef CODEGEN_X86_64_H
 #define CODEGEN_X86_64_H
 
+#include "arena.h"
 #include "ast.h"
+#include "map.h"
+#include <stdio.h>
+
+typedef struct codegen_x86_64
+{
+    arena_t *arena;
+    size_t base_offset;
+    map_t *symbols_stack_offset;
+    FILE *out;
+} codegen_x86_64_t;
+
+void
+codegen_linux_x86_64_init(codegen_x86_64_t *codegen, arena_t *arena, FILE *out);
 
 void
-codegen_linux_x86_64_emit_program(FILE *out, ast_node_t *prog);
+codegen_linux_x86_64_emit_program(codegen_x86_64_t *codegen, ast_node_t *prog);
 
 #endif /* CODEGEN_X86_64_H */
diff --git a/src/main.c b/src/main.c
index 810bf2d..312b0c1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -147,10 +147,14 @@ handle_codegen_linux(cli_opts_t *opts)
     assert(out);
 
     if (!(opts->options & CLI_OPT_ARCH)) {
-        codegen_linux_x86_64_emit_program(out, ast);
+        codegen_x86_64_t codegen = { 0 };
+        codegen_linux_x86_64_init(&codegen, &arena, out);
+        codegen_linux_x86_64_emit_program(&codegen, ast);
     } else {
         if (strcmp(opts->arch, "x86_64") == 0) {
-            codegen_linux_x86_64_emit_program(out, ast);
+            codegen_x86_64_t codegen = { 0 };
+            codegen_linux_x86_64_init(&codegen, &arena, out);
+            codegen_linux_x86_64_emit_program(&codegen, ast);
         } else if (strcmp(opts->arch, "aarch64") == 0) {
             codegen_linux_aarch64_emit_program(out, ast);
         } else {
diff --git a/tests/integration/tests/0024_var_definition.ol b/tests/integration/tests/0024_var_definition.ol
index 241fc1a..5c23449 100644
--- a/tests/integration/tests/0024_var_definition.ol
+++ b/tests/integration/tests/0024_var_definition.ol
@@ -18,6 +18,10 @@ fn main(): u32 {
   return code
 }
 
+# TEST test_compile(exit_code=0)
+
+# TEST test_run_binary(exit_code=0)
+
 # TEST test_contains_tokens WITH
 # ./tests/0024_var_definition.ol:17:3: <var>
 # END
-- 
2.46.0


  parent reply	other threads:[~2024-09-21  0:22 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-21  0:20 [PATCH olang v1 0/3] compiler: enable full compilation for vars Johnny Richard
2024-09-21  0:20 ` [PATCH olang v1 1/3] scope: create scope data structure Johnny Richard
2024-09-21  0:20 ` [PATCH olang v1 2/3] checker: create checker and populate scope on ast nodes Johnny Richard
2024-09-21  0:20 ` Johnny Richard [this message]
2024-09-21  0:23   ` [olang/patches/.build.yml] build success builds.sr.ht
2024-09-21  0:59 ` [PATCH olang v1 0/3] compiler: enable full compilation for vars Carlos Maniero

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240921002250.902558-4-johnny@johnnyrichard.com \
    --to=johnny@johnnyrichard.com \
    --cc=~johnnyrichard/olang-devel@lists.sr.ht \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.johnnyrichard.com/olang.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox