#include "codegen.h" #include #include #include struct unit_codegen_state { struct code_generator_state s_base; struct code_generator_scope *s_scope; /* function for top-level statements */ // struct mie_block *s_immediate_alloca; struct mie_func *s_immediate; }; static enum ivy_status switch_to_immediate_func( struct ivy_codegen *gen, struct unit_codegen_state *unit) { if (!unit->s_immediate) { struct mie_type *ret_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_VOID); unit->s_immediate = mie_func_create( "init", MIE_FUNC_STATIC, ret_type, NULL, 0); if (!unit->s_immediate) { return IVY_ERR_NO_MEMORY; } mie_module_add_function(gen->c_module, unit->s_immediate); } struct mie_block *block = mie_func_get_last_block(unit->s_immediate); if (!block) { #if 0 unit->s_immediate_alloca = mie_func_create_block(unit->s_immediate, "alloca"); mie_func_insert_block( unit->s_immediate, unit->s_immediate_alloca, NULL); #endif block = mie_func_create_block(unit->s_immediate, "entry"); mie_func_insert_block(unit->s_immediate, block, NULL); } if (mie_block_is_terminated(block)) { block = mie_func_create_block(unit->s_immediate, NULL); mie_func_insert_block(unit->s_immediate, block, NULL); } mie_builder_set_insert_point(gen->c_builder, block); return IVY_OK; } #if 0 static enum ivy_status switch_to_immediate_alloca( struct ivy_codegen *gen, struct unit_codegen_state *unit) { enum ivy_status status = switch_to_immediate_func(gen, unit); if (status != IVY_OK) { return status; } mie_builder_set_insert_point(gen->c_builder, unit->s_immediate_alloca); return IVY_OK; } #endif static struct code_generator_result gen_expr( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { struct unit_codegen_state *unit = (struct unit_codegen_state *)state; struct mie_builder *builder = gen->c_builder; struct mie_func *current = mie_builder_get_current_func(builder); enum ivy_status status = IVY_OK; if (!current || current != unit->s_immediate) { status = switch_to_immediate_func(gen, unit); } if (status != IVY_OK) { return CODEGEN_RESULT_ERR(status); } codegen_push_generator( gen, CODE_GENERATOR_EXPR, CODEGEN_F_IGNORE_RESULT, NULL); return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } static struct code_generator_result gen_var_declaration( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { struct unit_codegen_state *unit = (struct unit_codegen_state *)state; struct mie_builder *builder = gen->c_builder; struct mie_func *current = mie_builder_get_current_func(builder); enum ivy_status status = IVY_OK; if (!current || current != unit->s_immediate) { status = switch_to_immediate_func(gen, unit); } if (status != IVY_OK) { return CODEGEN_RESULT_ERR(status); } codegen_push_generator(gen, CODE_GENERATOR_VAR, 0, NULL); return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } #if 0 static struct code_generator_result gen_var_declaration( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node) { struct unit_codegen_state *unit = (struct unit_codegen_state *)state; struct mie_builder *builder = gen->c_builder; struct mie_block *current_block = mie_builder_get_current_block(gen->c_builder); enum ivy_status status = IVY_OK; if (!current_block || current_block != unit->s_immediate_alloca) { status = switch_to_immediate_alloca(gen, unit); } struct codegen_value *value = codegen_pop_value(gen); struct codegen_value *dest = codegen_pop_value(gen); if (!dest) { return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); } struct mie_type *id_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); struct mie_value *var_ptr = mie_builder_alloca(builder, id_type, NULL); if (value) { mie_builder_store(builder, value->v_value, var_ptr); } code_generator_scope_put_variable( unit->s_scope, (struct ivy_ast_ident_node *)dest->v_node, var_ptr); return CODEGEN_RESULT_OK(0); } #endif static enum ivy_status state_init( struct ivy_codegen *gen, struct code_generator_state *state, uintptr_t argv, void *argp) { struct unit_codegen_state *unit = (struct unit_codegen_state *)state; unit->s_scope = codegen_push_scope(gen); return IVY_OK; } static enum ivy_status state_fini( struct ivy_codegen *gen, struct code_generator_state *state, struct mie_value **result) { codegen_pop_scope(gen); return IVY_OK; } struct code_generator unit_generator = { .g_type = CODE_GENERATOR_UNIT, .g_state_size = sizeof(struct unit_codegen_state), .g_state_init = state_init, .g_state_fini = state_fini, .g_node_generators = { NODE_CODEGEN(VAR, gen_var_declaration), }, .g_expr_generator = gen_expr, };