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
110
codegen.c
110
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: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue