From c442e53ffee737fbb4274945c24b722960c958ed Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 8 Sep 2025 16:26:12 +0100 Subject: [PATCH] lang: codegen: implement while-loop code generation --- lang/codegen/generator.c | 2 + lang/codegen/unit.c | 23 ++++++ lang/codegen/while-loop.c | 154 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 lang/codegen/while-loop.c diff --git a/lang/codegen/generator.c b/lang/codegen/generator.c index cda094e..eecea7f 100644 --- a/lang/codegen/generator.c +++ b/lang/codegen/generator.c @@ -13,6 +13,7 @@ extern const struct code_generator return_generator; extern const struct code_generator cond_generator; extern const struct code_generator cond_group_generator; extern const struct code_generator for_loop_generator; +extern const struct code_generator while_loop_generator; static const struct code_generator *code_generators[] = { [CODE_GENERATOR_UNIT] = &unit_generator, @@ -26,6 +27,7 @@ static const struct code_generator *code_generators[] = { [CODE_GENERATOR_COND] = &cond_generator, [CODE_GENERATOR_COND_GROUP] = &cond_group_generator, [CODE_GENERATOR_FOR_LOOP] = &for_loop_generator, + [CODE_GENERATOR_WHILE_LOOP] = &while_loop_generator, }; static const size_t nr_code_generators = sizeof code_generators / sizeof code_generators[0]; diff --git a/lang/codegen/unit.c b/lang/codegen/unit.c index ef9853f..09860a8 100644 --- a/lang/codegen/unit.c +++ b/lang/codegen/unit.c @@ -120,6 +120,28 @@ static struct code_generator_result gen_for_loop( return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } +static struct code_generator_result gen_while_loop( + 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, ENSURE_OPEN_BLOCK); + } + + if (status != IVY_OK) { + return CODEGEN_RESULT_ERR(status); + } + + codegen_push_generator( + gen, CODE_GENERATOR_WHILE_LOOP, CODEGEN_F_IGNORE_RESULT, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + static void serialise_package_name(b_queue *parts, b_stringstream *out) { b_stringstream_add(out, "_ZN"); @@ -274,6 +296,7 @@ struct code_generator unit_generator = { .g_node_generators = { NODE_CODEGEN(RETURN, gen_return), NODE_CODEGEN(FOR_LOOP, gen_for_loop), + NODE_CODEGEN(WHILE_LOOP, gen_while_loop), NODE_CODEGEN(UNIT_PACKAGE, gen_unit_package), NODE_CODEGEN(UNIT_IMPORT, gen_unit_import), }, diff --git a/lang/codegen/while-loop.c b/lang/codegen/while-loop.c new file mode 100644 index 0000000..269beec --- /dev/null +++ b/lang/codegen/while-loop.c @@ -0,0 +1,154 @@ +#include "codegen.h" + +#include +#include +#include + +struct while_codegen_state { + struct code_generator_state s_base; + struct mie_value *s_cond_value; + + struct { + struct mie_block *b_cond; + struct mie_block *b_body; + 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 while_codegen_state *while_loop + = (struct while_codegen_state *)state; + + if (!while_loop->s_cond_value) { + mie_builder_br(gen->c_builder, while_loop->s_blocks.b_cond); + + struct mie_func *func + = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, while_loop->s_blocks.b_cond, NULL); + mie_builder_set_insert_point( + gen->c_builder, while_loop->s_blocks.b_cond); + } + + codegen_push_generator(gen, CODE_GENERATOR_EXPR, 0, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + +static struct code_generator_result gen_while_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 while_codegen_state *while_loop + = (struct while_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + // mie_builder_br(gen->c_builder, while_loop->s_blocks.b_cond); + // mie_func_insert_block(func, while_loop->s_blocks.b_cond, NULL); + // mie_builder_set_insert_point(gen->c_builder, while_loop->s_blocks.b_cond); + + codegen_push_generator(gen, CODE_GENERATOR_BLOCK, 0, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + +static enum ivy_status state_init( + struct ivy_codegen *gen, struct code_generator_state *state, + uintptr_t argv, void *argp) +{ + struct while_codegen_state *while_loop + = (struct while_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + while_loop->s_blocks.b_cond = mie_func_create_block(func, "while.cond"); + while_loop->s_blocks.b_body = mie_func_create_block(func, "while.body"); + while_loop->s_blocks.b_end = mie_func_create_block(func, "while.end"); + + state->s_loop_break_target = while_loop->s_blocks.b_end; + state->s_loop_repeat_target = while_loop->s_blocks.b_cond; + + return IVY_OK; +} + +static enum ivy_status gen_cond_branch( + struct ivy_codegen *gen, struct while_codegen_state *while_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + mie_builder_br_if( + gen->c_builder, while_loop->s_cond_value, + while_loop->s_blocks.b_body, while_loop->s_blocks.b_end); + + return IVY_OK; +} + +static enum ivy_status gen_body( + struct ivy_codegen *gen, struct while_codegen_state *while_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, while_loop->s_blocks.b_body, NULL); + mie_builder_set_insert_point(gen->c_builder, while_loop->s_blocks.b_body); + + return IVY_OK; +} + +static enum ivy_status gen_end_block( + struct ivy_codegen *gen, struct while_codegen_state *while_loop) +{ + mie_builder_br(gen->c_builder, while_loop->s_blocks.b_cond); + + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, while_loop->s_blocks.b_end, NULL); + mie_builder_set_insert_point(gen->c_builder, while_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 while_codegen_state *while_loop + = (struct while_codegen_state *)state; + gen_end_block(gen, while_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 while_codegen_state *while_loop + = (struct while_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + if (!while_loop->s_cond_value) { + while_loop->s_cond_value + = code_generator_value_get_mie_value(value); + gen_cond_branch(gen, while_loop); + gen_body(gen, while_loop); + return CODEGEN_RESULT_OK(0); + } + + return CODEGEN_RESULT_OK(0); +} + +struct code_generator while_loop_generator = { + .g_type = CODE_GENERATOR_WHILE_LOOP, + .g_state_size = sizeof(struct while_codegen_state), + .g_state_init = state_init, + .g_state_fini = state_fini, + .g_value_received = value_received, + .g_expr_generator = gen_expr, + .g_node_generators = { + NODE_CODEGEN(WHILE_LOOP, gen_while_loop), + NODE_CODEGEN(BLOCK, gen_block), + }, +};