#include "codegen.h" #include #include #include struct for_codegen_state { struct code_generator_state s_base; struct ivy_ast_ident_node *s_it_ident; struct mie_value *s_container; struct mie_value *s_iterator; struct mie_value *s_it_value, *s_it_value_inner; struct mie_value *s_it_finished; struct { struct mie_block *b_cond; struct mie_block *b_body; struct mie_block *b_inc; struct mie_block *b_end; } s_blocks; }; 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 for_codegen_state *for_loop = (struct for_codegen_state *)state; codegen_push_generator(gen, CODE_GENERATOR_EXPR, 0, NULL); return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } static struct code_generator_result gen_ident( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; if (!for_loop->s_it_ident) { for_loop->s_it_ident = (struct ivy_ast_ident_node *)node; return CODEGEN_RESULT_OK(0); } return gen_expr(gen, state, node, depth); } static struct code_generator_result gen_for_loop( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { return CODEGEN_RESULT_OK(0); } static struct code_generator_result gen_block( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; struct mie_func *func = mie_builder_get_current_func(gen->c_builder); // mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); // mie_func_insert_block(func, for_loop->s_blocks.b_cond, NULL); // mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_cond); codegen_push_generator(gen, CODE_GENERATOR_BLOCK, 0, NULL); return CODEGEN_RESULT_OK(0); } static enum ivy_status state_init( struct ivy_codegen *gen, struct code_generator_state *state, uintptr_t argv, void *argp) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; struct mie_func *func = mie_builder_get_current_func(gen->c_builder); for_loop->s_blocks.b_cond = mie_func_create_block(func, "for.cond"); for_loop->s_blocks.b_body = mie_func_create_block(func, "for.body"); for_loop->s_blocks.b_inc = mie_func_create_block(func, "for.inc"); for_loop->s_blocks.b_end = mie_func_create_block(func, "for.end"); state->s_loop_break_target = for_loop->s_blocks.b_end; state->s_loop_repeat_target = for_loop->s_blocks.b_inc; return IVY_OK; } static enum ivy_status gen_iterator_start( struct ivy_codegen *gen, struct for_codegen_state *for_loop) { struct mie_func *func = mie_builder_get_current_func(gen->c_builder); struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M8iteratorE"); for_loop->s_iterator = mie_builder_msg( gen->c_builder, id, for_loop->s_container, sel, NULL, 0, 0, "for.it"); mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); return IVY_OK; } static enum ivy_status gen_cond_block( struct ivy_codegen *gen, struct for_codegen_state *for_loop) { struct mie_func *func = mie_builder_get_current_func(gen->c_builder); mie_func_insert_block(func, for_loop->s_blocks.b_cond, NULL); mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_cond); struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M5valueE"); struct mie_value *null_value = mie_ctx_get_null(gen->c_ctx); for_loop->s_it_value = mie_builder_msg( gen->c_builder, id, for_loop->s_iterator, sel, NULL, 0, 0, "for.value"); for_loop->s_it_finished = mie_builder_cmp_eq( gen->c_builder, for_loop->s_it_value, null_value, "for.finished"); mie_builder_br_if( gen->c_builder, for_loop->s_it_finished, for_loop->s_blocks.b_end, for_loop->s_blocks.b_body); return IVY_OK; } static enum ivy_status gen_body( struct ivy_codegen *gen, struct for_codegen_state *for_loop) { struct mie_func *func = mie_builder_get_current_func(gen->c_builder); mie_func_insert_block(func, for_loop->s_blocks.b_body, NULL); mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_body); struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); for_loop->s_it_value_inner = mie_builder_alloca( gen->c_builder, id, for_loop->s_it_ident->n_content->t_str); mie_builder_store( gen->c_builder, for_loop->s_it_value, for_loop->s_it_value_inner); return IVY_OK; } static enum ivy_status gen_inc_block( struct ivy_codegen *gen, struct for_codegen_state *for_loop) { struct mie_func *func = mie_builder_get_current_func(gen->c_builder); mie_builder_br(gen->c_builder, for_loop->s_blocks.b_inc); mie_func_insert_block(func, for_loop->s_blocks.b_inc, NULL); mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_inc); struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M8moveNextE"); mie_builder_msg( gen->c_builder, id, for_loop->s_iterator, sel, NULL, 0, 0, NULL); mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); return IVY_OK; } static enum ivy_status gen_end_block( struct ivy_codegen *gen, struct for_codegen_state *for_loop) { struct mie_func *func = mie_builder_get_current_func(gen->c_builder); mie_func_insert_block(func, for_loop->s_blocks.b_end, NULL); mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_end); return IVY_OK; } static enum ivy_status state_fini( struct ivy_codegen *gen, struct code_generator_state *state, struct code_generator_value *result) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; gen_inc_block(gen, for_loop); gen_end_block(gen, for_loop); return IVY_OK; } static struct code_generator_result value_received( struct ivy_codegen *gen, struct code_generator_state *state, struct code_generator_value *value) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; struct mie_func *func = mie_builder_get_current_func(gen->c_builder); if (!for_loop->s_container) { for_loop->s_container = code_generator_value_get_mie_value(value); gen_iterator_start(gen, for_loop); gen_cond_block(gen, for_loop); gen_body(gen, for_loop); return CODEGEN_RESULT_OK(0); } return CODEGEN_RESULT_OK(0); } static enum ivy_status resolve_var( struct ivy_codegen *gen, struct code_generator_state *state, const char *ident, struct codegen_var *var) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; if (strcmp(ident, for_loop->s_it_ident->n_content->t_str) != 0) { return IVY_ERR_NO_ENTRY; } var->v_node = (struct ivy_ast_node *)for_loop->s_it_ident; var->v_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); var->v_value = for_loop->s_it_value_inner; var->v_flags = CODEGEN_VAR_F_PTR; return IVY_OK; } struct code_generator for_loop_generator = { .g_type = CODE_GENERATOR_FOR_LOOP, .g_state_size = sizeof(struct for_codegen_state), .g_state_init = state_init, .g_state_fini = state_fini, .g_resolve_var = resolve_var, .g_value_received = value_received, .g_expr_generator = gen_expr, .g_node_generators = { NODE_CODEGEN(FOR_LOOP, gen_for_loop), NODE_CODEGEN(IDENT, gen_ident), NODE_CODEGEN(BLOCK, gen_block), }, };