#include "../debug.h" #include "codegen.h" #include struct expr_codegen_state { struct code_generator_state s_base; struct ivy_ast_node *s_expr_root; }; static struct code_generator_result check_expr_root( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node) { struct expr_codegen_state *expr = (struct expr_codegen_state *)state; if (!expr->s_expr_root) { expr->s_expr_root = node; } return CODEGEN_RESULT_OK(0); } static struct code_generator_result gen_int( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node) { struct expr_codegen_state *expr = (struct expr_codegen_state *)state; debug_printf("codegen: got int\n"); struct ivy_ast_int_node *int_node = (struct ivy_ast_int_node *)node; struct mie_value *value = mie_ctx_get_int(gen->c_ctx, int_node->n_value->t_int, 32); codegen_push_value(gen, value); if (node == expr->s_expr_root) { codegen_pop_generator(gen); } return CODEGEN_RESULT_OK(0); } static struct code_generator_result gen_op( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node) { struct expr_codegen_state *expr = (struct expr_codegen_state *)state; debug_printf("codegen: got operator\n"); struct mie_value *left = codegen_pop_value(gen); struct mie_value *right = codegen_pop_value(gen); if (!left || !right) { return CODEGEN_RESULT_ERR(IVY_ERR_INVALID_VALUE); } struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)node; const struct ivy_operator *op = op_node->n_op; struct mie_value *op_instr = NULL; switch (op->op_id) { case IVY_OP_ADD: op_instr = mie_builder_add(gen->c_builder, left, right, "addtmp"); break; case IVY_OP_SUBTRACT: op_instr = mie_builder_sub(gen->c_builder, left, right, "subtmp"); break; case IVY_OP_MULTIPLY: op_instr = mie_builder_mul(gen->c_builder, left, right, "multmp"); break; case IVY_OP_DIVIDE: op_instr = mie_builder_div(gen->c_builder, left, right, "divtmp"); break; default: mie_value_destroy(left); mie_value_destroy(right); return CODEGEN_RESULT_ERR(IVY_ERR_NOT_SUPPORTED); } if (!op_instr) { mie_value_destroy(left); mie_value_destroy(right); return CODEGEN_RESULT_ERR(IVY_ERR_NO_MEMORY); } codegen_push_value(gen, op_instr); if (node == expr->s_expr_root) { codegen_pop_generator(gen); } return CODEGEN_RESULT_OK(0); } static enum ivy_status state_init( struct ivy_codegen *gen, struct code_generator_state *state) { debug_printf("codegen: start of expression\n"); return IVY_OK; } static enum ivy_status state_fini( struct ivy_codegen *gen, struct code_generator_state *state) { debug_printf("codegen: end of expression\n"); return IVY_OK; } struct code_generator expr_generator = { .g_type = CODE_GENERATOR_UNIT, .g_state_size = sizeof(struct expr_codegen_state), .g_state_init = state_init, .g_state_fini = state_fini, .g_node_generators_pre = { [IVY_AST_INT] = check_expr_root, [IVY_AST_OP] = check_expr_root, }, .g_node_generators_post = { [IVY_AST_INT] = gen_int, [IVY_AST_OP] = gen_op, }, };