ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

commit b1397ecf38cef8fd371d4fb51b45a273b230b2c0
parent 2fba18d005233ab3a053baf6a8da086a27c40f87
Author: citbl <citbl@citbl.org>
Date:   Thu, 23 Oct 2025 21:53:05 +1000

refac

Diffstat:
Msrc/gen/gen.c | 216++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 115 insertions(+), 101 deletions(-)

diff --git a/src/gen/gen.c b/src/gen/gen.c @@ -303,6 +303,118 @@ static bool build_block(Gen* gen, Node* body); static int block_counter = 0; static bool +build_if_statement(Gen* gen, Node* node) +{ + gcc_jit_location* loc = loc_from_node(gen, node); + // build the condition + + OpType op = node->data.if_statement.cond->data.binary_expr.op; + Node* lhs = node->data.if_statement.cond->data.binary_expr.lhs; + Node* rhs = node->data.if_statement.cond->data.binary_expr.rhs; + + Node* then_body = node->data.if_statement.then_body; + Node* else_body = node->data.if_statement.else_body; + + enum gcc_jit_comparison cmp; + switch (op) { + case OP_EQUALITY: + cmp = GCC_JIT_COMPARISON_EQ; + break; + case OP_INEQUALITY: + cmp = GCC_JIT_COMPARISON_NE; + break; + default: + printf("build_statement NODE_IF unhandled, %d\n", op); + cmp = GCC_JIT_COMPARISON_EQ; + } + + gcc_jit_rvalue* lhs_val = handle_expr(gen, lhs); + gcc_jit_rvalue* rhs_val = handle_expr(gen, rhs); + + gcc_jit_rvalue* cond = gcc_jit_context_new_comparison(gen->ctx, loc, cmp, lhs_val, rhs_val); + + // create the BLOCKS + + // labels + block_counter++; + char label_then[64], label_else[64], label_end[64]; + snprintf(label_then, 64, "if.then%d", block_counter); + snprintf(label_else, 64, "if.else%d", block_counter); + snprintf(label_end, 64, "if.end%d", block_counter); + + // blocks + gcc_jit_block* then_bb = gcc_jit_function_new_block(gen->curr_func, label_then); + gcc_jit_block* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL; + gcc_jit_block* merge_bb = NULL; + + if (!else_bb) { + // no else: need merge now for the false edge + merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); + gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, merge_bb); + } else { + // with else: branch to then/else; decide on merge later + gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, else_bb); + } + + // THEN + gen->curr_block = then_bb; + bool then_ended = build_block(gen, then_body); + gcc_jit_block* then_open = gen->curr_block; // last open block in THEN (may differ from then_bb) + + // ELSE + bool else_ended = false; + gcc_jit_block* else_open = NULL; + if (else_bb) { + gen->curr_block = else_bb; + else_ended = build_block(gen, else_body); + else_open = gen->curr_block; // last open block in ELSE + } + + // If both branches ended, no merge needed, we notify we have ended as well + if (else_bb && then_ended && else_ended) return true; + + // Ensure we have a merge if any branch continues. + if (!merge_bb) merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); + + if (!then_ended) gcc_jit_block_end_with_jump(then_open, loc, merge_bb); + if (else_bb && !else_ended) gcc_jit_block_end_with_jump(else_open, loc, merge_bb); + + gen->curr_block = merge_bb; + return false; +} + +static bool +build_var_decl_statement(Gen* gen, Node* node) +{ + gcc_jit_location* loc = loc_from_node(gen, node); + const char* var_name = span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 }); + gcc_jit_type* declared_type = ox_type_to_c_type(gen, node->data.var_decl.type); + + gcc_jit_lvalue* var_decl = NULL; + gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_decl.init); + + if (gen->curr_func == NULL && gen->curr_block == NULL) { + var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name)); + gcc_jit_global_set_initializer_rvalue(var_decl, rvalue); + } else { + var_decl = gcc_jit_function_new_local(gen->curr_func, loc, declared_type, strdup(var_name)); + gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue); + } + + if (node->data.var_decl.init == NULL) { panic("could not instanciate gcc jit new local"); } + + printf("adding 1 symbol: %s\n", var_name); + + Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); + sym->name = node->data.var_decl.name; + sym->decl = node; + sym->ctype = declared_type; + sym->d.lvalue = var_decl; + add_symbol(gen, sym); + return false; +} + +static bool build_statement(Gen* gen, Node* node) { gcc_jit_location* loc = loc_from_node(gen, node); @@ -316,31 +428,7 @@ build_statement(Gen* gen, Node* node) return true; // we end the block here } case NODE_VAR_DECL: { - const char* var_name = span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 }); - gcc_jit_type* declared_type = ox_type_to_c_type(gen, node->data.var_decl.type); - - gcc_jit_lvalue* var_decl = NULL; - gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_decl.init); - - if (gen->curr_func == NULL && gen->curr_block == NULL) { - var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name)); - gcc_jit_global_set_initializer_rvalue(var_decl, rvalue); - } else { - var_decl = gcc_jit_function_new_local(gen->curr_func, loc, declared_type, strdup(var_name)); - gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue); - } - - if (node->data.var_decl.init == NULL) { panic("could not instanciate gcc jit new local"); } - - printf("adding 1 symbol: %s\n", var_name); - - Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); - sym->name = node->data.var_decl.name; - sym->decl = node; - sym->ctype = declared_type; - sym->d.lvalue = var_decl; - add_symbol(gen, sym); - break; + return build_var_decl_statement(gen, node); } case NODE_VAR_ASSIGN: { gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_assign.rhs); @@ -365,82 +453,8 @@ build_statement(Gen* gen, Node* node) if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); break; } - case NODE_IF: { - // build the condition - - OpType op = node->data.if_statement.cond->data.binary_expr.op; - Node* lhs = node->data.if_statement.cond->data.binary_expr.lhs; - Node* rhs = node->data.if_statement.cond->data.binary_expr.rhs; - - Node* then_body = node->data.if_statement.then_body; - Node* else_body = node->data.if_statement.else_body; - - enum gcc_jit_comparison cmp; - switch (op) { - case OP_EQUALITY: - cmp = GCC_JIT_COMPARISON_EQ; - break; - case OP_INEQUALITY: - cmp = GCC_JIT_COMPARISON_NE; - break; - default: - printf("build_statement NODE_IF unhandled, %d\n", op); - cmp = GCC_JIT_COMPARISON_EQ; - } - - gcc_jit_rvalue* lhs_val = handle_expr(gen, lhs); - gcc_jit_rvalue* rhs_val = handle_expr(gen, rhs); - gcc_jit_rvalue* cond = gcc_jit_context_new_comparison(gen->ctx, loc, cmp, lhs_val, rhs_val); - - // create the BLOCKS - - // labels - block_counter++; - char label_then[64], label_else[64], label_end[64]; - snprintf(label_then, 64, "if.then%d", block_counter); - snprintf(label_else, 64, "if.else%d", block_counter); - snprintf(label_end, 64, "if.end%d", block_counter); - - // blocks - gcc_jit_block* then_bb = gcc_jit_function_new_block(gen->curr_func, label_then); - gcc_jit_block* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL; - gcc_jit_block* merge_bb = NULL; - - if (!else_bb) { - // no else: need merge now for the false edge - merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); - gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, merge_bb); - } else { - // with else: branch to then/else; decide on merge later - gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_bb, else_bb); - } - - // THEN - gen->curr_block = then_bb; - bool then_ended = build_block(gen, then_body); - gcc_jit_block* then_open = gen->curr_block; // last open block in THEN (may differ from then_bb) - - // ELSE - bool else_ended = false; - gcc_jit_block* else_open = NULL; - if (else_bb) { - gen->curr_block = else_bb; - else_ended = build_block(gen, else_body); - else_open = gen->curr_block; // last open block in ELSE - } - - // If both branches ended, no merge needed, we notify we have ended as well - if (else_bb && then_ended && else_ended) return true; - - // Ensure we have a merge if any branch continues. - if (!merge_bb) merge_bb = gcc_jit_function_new_block(gen->curr_func, label_end); - - if (!then_ended) gcc_jit_block_end_with_jump(then_open, loc, merge_bb); - if (else_bb && !else_ended) gcc_jit_block_end_with_jump(else_open, loc, merge_bb); - - gen->curr_block = merge_bb; - return false; - } + case NODE_IF: + return build_if_statement(gen, node); default: printf("build_statement unhandled, %s\n", node_type_str(node->type)); break;