implement array subscript for assignment in codegen
This commit is contained in:
parent
870cf8f0b4
commit
667769d1c0
3 changed files with 195 additions and 5 deletions
108
codegen.c
108
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) {
|
||||
fprintf(fp, "# ERROR: left side of assignment must be identifier\n");
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OP_ASSIGN_PTR: {
|
||||
|
|
|
|||
BIN
test
Executable file
BIN
test
Executable file
Binary file not shown.
90
test.s
Normal file
90
test.s
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue