static void emit_store(Node *var) { SAVE; switch (var->type) { case AST_DEREF: emit_assign_deref(var); break; case AST_STRUCT_REF: emit_assign_struct_ref(var->struc, var->ctype, 0); break; case AST_LVAR: ensure_lvar_init(var); emit_lsave(var->ctype, var->loff); break; case AST_GVAR: emit_gsave(var->varname, var->ctype, 0); break; default: error("internal error"); } }
static void emit_addr(Node *node) { switch (node->type) { case AST_LVAR: ensure_lvar_init(node); emit("lea %d(%%rbp), %%rax", node->loff); break; case AST_GVAR: emit("lea %s(%%rip), %%rax", node->glabel); break; case AST_DEREF: emit_expr(node->operand); break; case AST_STRUCT_REF: emit_addr(node->struc); emit("add $%d, %%rax", node->ctype->offset); break; default: error("internal error: %s", a2s(node)); } }
static void emit_load_struct_ref(Node *struc, Ctype *field, int off) { SAVE; switch (struc->type) { case AST_LVAR: ensure_lvar_init(struc); emit_lload(field, "rbp", struc->loff + field->offset + off); break; case AST_GVAR: emit_gload(field, struc->varname, field->offset + off); break; case AST_STRUCT_REF: emit_load_struct_ref(struc->struc, field, struc->ctype->offset + off); break; case AST_DEREF: emit_expr(struc->operand); emit_lload(field, "rax", field->offset + off); break; default: error("internal error: %s", a2s(struc)); } }
static void emit_assign_struct_ref(Node *struc, Ctype *field, int off) { SAVE; switch (struc->type) { case AST_LVAR: ensure_lvar_init(struc); emit_lsave(field, struc->loff + field->offset + off); break; case AST_GVAR: emit_gsave(struc->varname, field, field->offset + off); break; case AST_STRUCT_REF: emit_assign_struct_ref(struc->struc, field, off + struc->ctype->offset); break; case AST_DEREF: push("rax"); emit_expr(struc->operand); emit_assign_deref_int(field, field->offset + off); break; default: error("internal error: %s", a2s(struc)); } }
static void emit_addr(Node *node) { switch (node->kind) { case AST_LVAR: ensure_lvar_init(node); emit("lea %d(#rbp), #rax", node->loff); break; case AST_GVAR: emit("lea %s(#rip), #rax", node->glabel); break; case AST_DEREF: emit_expr(node->operand); break; case AST_STRUCT_REF: emit_addr(node->struc); emit("add $%d, #rax", node->ty->offset); break; case AST_FUNCDESG: emit("lea %s(#rip), #rax", node->fname); break; default: error("internal error: %s", node2s(node)); } }
static void emit_lvar(Node *node) { SAVE; ensure_lvar_init(node); emit_lload(node->ctype, "rbp", node->loff); }