From 667769d1c0d963114ca9c026a7ed039734de10e2 Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Sat, 17 Jan 2026 10:33:19 +0100 Subject: [PATCH] implement array subscript for assignment in codegen --- codegen.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++--- test | Bin 0 -> 20368 bytes test.s | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 5 deletions(-) create mode 100755 test create mode 100644 test.s diff --git a/codegen.c b/codegen.c index 552bb77..d1c58fd 100644 --- a/codegen.c +++ b/codegen.c @@ -152,14 +152,114 @@ void gen_binary(FILE *fp, ast_node *expr) fprintf(fp, "or %%rcx, %%rax\n"); break; case OP_ASSIGN: { - if (expr->expr.binary.left->type != NODE_IDENTIFIER) { + if (expr->expr.binary.left->type == NODE_IDENTIFIER) { + gen_expr(fp, expr->expr.binary.right); + int offset = get_var_offset(expr->expr.binary.left->expr.string.start, + expr->expr.binary.left->expr.string.len); + fprintf(fp, "mov %%rax, -%d(%%rbp)\n", offset); + } else if (expr->expr.binary.left->type == NODE_ARRAY_SUBSCRIPT) { + ast_node *subscript = expr->expr.binary.left; + usize element_size = 8; + type *base_type = subscript->expr.subscript.expr->expr_type; + bool is_slice = false; + + if (base_type) { + if (base_type->tag == TYPE_PTR && base_type->data.ptr.child) { + element_size = base_type->data.ptr.child->size; + } else if (base_type->tag == TYPE_SLICE && base_type->data.slice.child) { + element_size = base_type->data.slice.child->size; + is_slice = true; + } + } + + if (subscript->expr.subscript.expr->type == NODE_IDENTIFIER && is_slice) { + int base_offset = get_var_offset(subscript->expr.subscript.expr->expr.string.start, + subscript->expr.subscript.expr->expr.string.len); + + fprintf(fp, "mov -%d(%%rbp), %%rcx\n", base_offset); + gen_expr(fp, subscript->expr.subscript.index); + + if (element_size != 1) { + fprintf(fp, "imul $%lu, %%rax\n", element_size); + } + + fprintf(fp, "add %%rcx, %%rax\n"); + fprintf(fp, "push %%rax\n"); + + gen_expr(fp, expr->expr.binary.right); + + fprintf(fp, "pop %%rcx\n"); + + if (subscript->expr_type && subscript->expr_type->size == 4) { + fprintf(fp, "mov %%eax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 2) { + fprintf(fp, "mov %%ax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 1) { + fprintf(fp, "mov %%al, (%%rcx)\n"); + } else { + fprintf(fp, "mov %%rax, (%%rcx)\n"); + } + } else if (subscript->expr.subscript.expr->type == NODE_IDENTIFIER) { + int base_offset = get_var_offset(subscript->expr.subscript.expr->expr.string.start, + subscript->expr.subscript.expr->expr.string.len); + + gen_expr(fp, subscript->expr.subscript.index); + + if (element_size != 1) { + fprintf(fp, "imul $%lu, %%rax\n", element_size); + } + + fprintf(fp, "add $%d, %%rax\n", base_offset); + fprintf(fp, "neg %%rax\n"); + fprintf(fp, "add %%rbp, %%rax\n"); + fprintf(fp, "push %%rax\n"); + + gen_expr(fp, expr->expr.binary.right); + + fprintf(fp, "pop %%rcx\n"); + + if (subscript->expr_type && subscript->expr_type->size == 4) { + fprintf(fp, "mov %%eax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 2) { + fprintf(fp, "mov %%ax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 1) { + fprintf(fp, "mov %%al, (%%rcx)\n"); + } else { + fprintf(fp, "mov %%rax, (%%rcx)\n"); + } + } else { + gen_expr(fp, subscript->expr.subscript.expr); + fprintf(fp, "push %%rax\n"); + + gen_expr(fp, subscript->expr.subscript.index); + + if (element_size != 1) { + fprintf(fp, "imul $%lu, %%rax\n", element_size); + } + + fprintf(fp, "pop %%rcx\n"); + fprintf(fp, "add %%rcx, %%rax\n"); + fprintf(fp, "push %%rax\n"); + + gen_expr(fp, expr->expr.binary.right); + + fprintf(fp, "pop %%rcx\n"); + + if (subscript->expr_type && subscript->expr_type->size == 4) { + fprintf(fp, "mov %%eax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 2) { + fprintf(fp, "mov %%ax, (%%rcx)\n"); + } else if (subscript->expr_type && subscript->expr_type->size == 1) { + fprintf(fp, "mov %%al, (%%rcx)\n"); + } else { + fprintf(fp, "mov %%rax, (%%rcx)\n"); + } + } + } else { fprintf(fp, "# ERROR: left side of assignment must be identifier\n"); break; } - gen_expr(fp, expr->expr.binary.right); - int offset = get_var_offset(expr->expr.binary.left->expr.string.start, - expr->expr.binary.left->expr.string.len); - fprintf(fp, "mov %%rax, -%d(%%rbp)\n", offset); + break; } case OP_ASSIGN_PTR: { diff --git a/test b/test new file mode 100755 index 0000000000000000000000000000000000000000..1b89d353242a021ce1ef52d7b784b465683311ed GIT binary patch literal 20368 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 literal 0 HcmV?d00001 diff --git a/test.s b/test.s new file mode 100644 index 0000000..b86c66e --- /dev/null +++ b/test.s @@ -0,0 +1,90 @@ +.section .text +.global main +main: +push %rbp +mov %rsp, %rbp +sub $256, %rsp +movb $72, -32(%rbp) +movb $101, -31(%rbp) +movb $108, -30(%rbp) +movb $108, -29(%rbp) +movb $111, -28(%rbp) +movb $32, -27(%rbp) +movb $119, -26(%rbp) +movb $111, -25(%rbp) +movb $114, -24(%rbp) +movb $108, -23(%rbp) +movb $100, -22(%rbp) +movb $33, -21(%rbp) +movb $10, -20(%rbp) +lea -32(%rbp), %rax +mov %rax, -48(%rbp) +mov $14, %rax +mov %rax, -40(%rbp) +mov -40(%rbp), %rax +push %rax +pop %rdi +call malloc +mov %rax, -56(%rbp) +mov -56(%rbp), %rcx +mov $0, %rax +push %rax +mov $13, %rax +mov %rax, %rdx +pop %rax +mov %rdx, %r8 +sub %rax, %r8 +inc %r8 +add %rcx, %rax +mov %rax, -88(%rbp) +mov %r8, -80(%rbp) +lea -88(%rbp), %rax +mov (%rax), %rcx +mov 8(%rax), %rdx +mov %rcx, -72(%rbp) +mov %rdx, -64(%rbp) +mov $0, %rax +mov %rax, -96(%rbp) +.L0: +mov -96(%rbp), %rax +mov %rax, %rcx +mov -40(%rbp), %rax +cmp %rax, %rcx +setl %al +movzx %al, %rax +test %rax, %rax +jz .L1 +mov -72(%rbp), %rcx +mov -96(%rbp), %rax +add %rcx, %rax +push %rax +mov -48(%rbp), %rcx +mov -96(%rbp), %rax +add %rcx, %rax +movzbl (%rax), %eax +pop %rcx +mov %al, (%rcx) +mov -96(%rbp), %rax +mov %rax, %rcx +mov $1, %rax +add %rcx, %rax +mov %rax, -96(%rbp) +jmp .L0 +.L1: +mov $1, %rax +push %rax +mov -72(%rbp), %rax +push %rax +mov -64(%rbp), %rax +push %rax +pop %rdx +pop %rsi +pop %rdi +call write +mov $0, %rax +mov %rbp, %rsp +pop %rbp +ret +mov %rbp, %rsp +pop %rbp +ret